Description
When using a BYOK Anthropic provider (type: "anthropic"), the assistant.turn_start and assistant.turn_end events are never emitted. All other events (assistant.usage, assistant.message, tool.execution_start, tool.execution_complete, session.idle) fire correctly.
The same session setup with the default backend or a BYOK OpenAI provider emits all turn lifecycle events as expected.
Reproduction
import asyncio
import os
from copilot import CopilotClient
from copilot.client import SubprocessConfig
from copilot.session import (
InfiniteSessionConfig,
PermissionHandler,
SystemMessageReplaceConfig,
)
from copilot.tools import Tool, ToolResult
async def my_tool(args):
return ToolResult(content="42")
async def run_test(client, label, model, provider=None):
events = []
def on_event(event):
events.append(event.type.value)
kwargs = dict(
on_permission_request=PermissionHandler.approve_all,
model=model,
system_message=SystemMessageReplaceConfig(
mode="replace", content="Use my_tool when asked."
),
available_tools=["my_tool"],
streaming=True,
tools=[Tool(name="my_tool", description="Returns 42", handler=my_tool)],
infinite_sessions=InfiniteSessionConfig(enabled=False),
on_event=on_event,
)
if provider:
kwargs["provider"] = provider
session = await client.create_session(**kwargs)
try:
await session.send_and_wait("Use my_tool to get the answer.", timeout=60)
finally:
await session.disconnect()
unique = set(events)
ts = events.count("assistant.turn_start")
te = events.count("assistant.turn_end")
print(f"{label}: turn_start={ts}, turn_end={te}, "
f"usage={events.count('assistant.usage')}, "
f"message={events.count('assistant.message')}")
return unique
async def main():
endpoint = os.environ["AZURE_FOUNDRY_ENDPOINT"].rstrip("/")
api_key = os.environ["AZURE_FOUNDRY_API_KEY"]
client = CopilotClient(SubprocessConfig())
try:
# 1. Default backend -- turn events fire
default = await run_test(client, "Default (claude-haiku-4.5)", "claude-haiku-4.5")
# 2. BYOK Anthropic (Haiku) -- turn events MISSING
byok_haiku = await run_test(client, "BYOK Anthropic (claude-haiku-4-5)", "claude-haiku-4-5", {
"type": "anthropic",
"base_url": f"{endpoint}/anthropic",
"api_key": api_key,
})
# 3. BYOK Anthropic (Sonnet) -- turn events MISSING
byok_sonnet = await run_test(client, "BYOK Anthropic (claude-sonnet-4-6)", "claude-sonnet-4-6", {
"type": "anthropic",
"base_url": f"{endpoint}/anthropic",
"api_key": api_key,
})
# 4. BYOK OpenAI -- turn events fire
byok_openai = await run_test(client, "BYOK OpenAI (gpt-5.4-nano)", "gpt-5.4-nano", {
"type": "openai",
"base_url": f"{endpoint}/openai/v1/",
"api_key": api_key,
"wire_api": "responses",
})
# Show events emitted by both Default and BYOK OpenAI
# but never delivered to on_event by BYOK Anthropic
missing = sorted((default | byok_openai) - byok_haiku)
if missing:
print(f"\nEvents missing from BYOK Anthropic that both others emit:")
for e in missing:
print(f" - {e}")
finally:
await client.stop()
asyncio.run(main())
Requires AZURE_FOUNDRY_ENDPOINT and AZURE_FOUNDRY_API_KEY env vars pointing to an Azure AI Foundry deployment with Anthropic and OpenAI models available.
Actual output (SDK 0.2.2)
Default (claude-haiku-4.5): turn_start=2, turn_end=2, usage=2, message=2
BYOK Anthropic (claude-haiku-4-5): turn_start=0, turn_end=0, usage=2, message=2
BYOK Anthropic (claude-sonnet-4-6): turn_start=0, turn_end=0, usage=2, message=2
BYOK OpenAI (gpt-5.4-nano): turn_start=2, turn_end=2, usage=2, message=2
Events missing from BYOK Anthropic that both others emit:
- assistant.reasoning
- assistant.reasoning_delta
- assistant.turn_end
- assistant.turn_start
- session.custom_agents_updated
- session.usage_info
Expected output
All three backends should emit assistant.turn_start and assistant.turn_end. The streaming events documentation lists both as non-ephemeral events that are always emitted, and the agent loop documentation states "the number of assistant.turn_start / assistant.turn_end pairs equals the total number of LLM API calls."
Additional missing events with BYOK Anthropic
Comparing unique event types across all three backends, BYOK Anthropic also does not emit these events that both Default and BYOK OpenAI do emit:
assistant.reasoning
assistant.reasoning_delta
session.usage_info
Note: session.custom_agents_updated is missing from both BYOK providers (Anthropic and OpenAI) but present in the default backend -- this may be a separate, broader BYOK issue.
Impact
Code that tracks per-turn token usage by accumulating assistant.usage data between turn_start/turn_end boundaries gets no per-turn stats with BYOK Anthropic. The assistant.usage events themselves fire correctly, so session-level totals can still be computed, but turn-level granularity is lost.
Environment
- SDK:
github-copilot-sdk==0.2.2 (also confirmed on 0.2.1)
- Provider: Azure AI Foundry with
type: "anthropic" provider config
- Models tested:
claude-haiku-4-5 and claude-sonnet-4-6 via BYOK Anthropic -- both missing turn events
- Controls: Default backend (
claude-haiku-4.5) and BYOK OpenAI (gpt-5.4-nano) on the same Foundry endpoint both emit turn events correctly
- OS: Windows 11
- Python: 3.12
Description
When using a BYOK Anthropic provider (
type: "anthropic"), theassistant.turn_startandassistant.turn_endevents are never emitted. All other events (assistant.usage,assistant.message,tool.execution_start,tool.execution_complete,session.idle) fire correctly.The same session setup with the default backend or a BYOK OpenAI provider emits all turn lifecycle events as expected.
Reproduction
Requires
AZURE_FOUNDRY_ENDPOINTandAZURE_FOUNDRY_API_KEYenv vars pointing to an Azure AI Foundry deployment with Anthropic and OpenAI models available.Actual output (SDK 0.2.2)
Expected output
All three backends should emit
assistant.turn_startandassistant.turn_end. The streaming events documentation lists both as non-ephemeral events that are always emitted, and the agent loop documentation states "the number ofassistant.turn_start/assistant.turn_endpairs equals the total number of LLM API calls."Additional missing events with BYOK Anthropic
Comparing unique event types across all three backends, BYOK Anthropic also does not emit these events that both Default and BYOK OpenAI do emit:
assistant.reasoningassistant.reasoning_deltasession.usage_infoNote:
session.custom_agents_updatedis missing from both BYOK providers (Anthropic and OpenAI) but present in the default backend -- this may be a separate, broader BYOK issue.Impact
Code that tracks per-turn token usage by accumulating
assistant.usagedata betweenturn_start/turn_endboundaries gets no per-turn stats with BYOK Anthropic. Theassistant.usageevents themselves fire correctly, so session-level totals can still be computed, but turn-level granularity is lost.Environment
github-copilot-sdk==0.2.2(also confirmed on 0.2.1)type: "anthropic"provider configclaude-haiku-4-5andclaude-sonnet-4-6via BYOK Anthropic -- both missing turn eventsclaude-haiku-4.5) and BYOK OpenAI (gpt-5.4-nano) on the same Foundry endpoint both emit turn events correctly