Python: Filter conversation_id when passing kwargs to agent as tool (#3266)

* Filter conversation_id when passing kwargs to agent as tool

* Small fix

* Update python/samples/getting_started/agents/azure_ai/README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update python/samples/getting_started/agents/openai/openai_responses_client_with_agent_as_tool.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update python/samples/getting_started/agents/azure_ai/azure_ai_with_agent_as_tool.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Dmytro Struk
2026-01-19 04:54:06 -08:00
committed by GitHub
Unverified
parent 915df3b404
commit 3243652df6
6 changed files with 182 additions and 2 deletions
@@ -470,8 +470,8 @@ class BaseAgent(SerializationMixin):
# Extract the input from kwargs using the specified arg_name
input_text = kwargs.get(arg_name, "")
# Forward all kwargs except the arg_name to support runtime context propagation
forwarded_kwargs = {k: v for k, v in kwargs.items() if k != arg_name}
# Forward runtime context kwargs, excluding arg_name and conversation_id.
forwarded_kwargs = {k: v for k, v in kwargs.items() if k not in (arg_name, "conversation_id")}
if stream_callback is None:
# Use non-streaming mode
@@ -313,3 +313,44 @@ class TestAsToolKwargsPropagation:
# Verify second call had its own kwargs (not leaked from first)
assert second_call_kwargs.get("session_id") == "session-2"
assert second_call_kwargs.get("api_token") == "token-2"
async def test_as_tool_excludes_conversation_id_from_forwarded_kwargs(self, chat_client: MockChatClient) -> None:
"""Test that conversation_id is not forwarded to sub-agent."""
captured_kwargs: dict[str, Any] = {}
@agent_middleware
async def capture_middleware(
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
) -> None:
captured_kwargs.update(context.kwargs)
await next(context)
# Setup mock response
chat_client.responses = [
ChatResponse(messages=[ChatMessage(role="assistant", text="Response from sub-agent")]),
]
sub_agent = ChatAgent(
chat_client=chat_client,
name="sub_agent",
middleware=[capture_middleware],
)
tool = sub_agent.as_tool(name="delegate", arg_name="task")
# Invoke tool with conversation_id in kwargs (simulating parent's conversation state)
await tool.invoke(
arguments=tool.input_model(task="Test delegation"),
conversation_id="conv-parent-456",
api_token="secret-xyz-123",
user_id="user-456",
)
# Verify conversation_id was NOT forwarded to sub-agent
assert "conversation_id" not in captured_kwargs, (
f"conversation_id should not be forwarded, but got: {captured_kwargs}"
)
# Verify other kwargs were still forwarded
assert captured_kwargs.get("api_token") == "secret-xyz-123"
assert captured_kwargs.get("user_id") == "user-456"