Files
2026-07-13 12:39:17 +08:00

93 lines
3.1 KiB
Python

# Copy/paste command (does not modify uv.lock):
# uv run -m examples.agent_patterns.hosted_multi_agent_beta --mode stream
import argparse
import asyncio
from collections.abc import Mapping
from typing import Any
from agents import Agent, Runner, function_tool
from agents.extensions.experimental.hosted_multi_agent import (
OpenAIHostedMultiAgentModel,
get_hosted_agent_metadata,
)
from agents.tool_context import ToolContext
PROPOSALS = {
"alpha": {"estimated_weeks": 6, "risk": "medium"},
"beta": {"estimated_weeks": 8, "risk": "low"},
}
@function_tool
def get_proposal(ctx: ToolContext[Any], proposal: str) -> dict[str, object]:
"""Return deterministic details for one proposal."""
metadata = get_hosted_agent_metadata(ctx)
caller = metadata.agent_name if metadata else "unknown"
print(f"local tool caller={caller} call_id={ctx.tool_call_id} proposal={proposal}")
if proposal not in PROPOSALS:
raise ValueError(f"Unknown proposal: {proposal}")
return PROPOSALS[proposal]
def build_agent() -> Agent[Any]:
return Agent(
name="Hosted proposal coordinator",
instructions=(
"Create two subagents. Ask one to inspect proposal alpha and the other to inspect "
"proposal beta. Each subagent must call get_proposal for its assigned proposal. "
"Wait for both results, then return one concise comparison from the root agent."
),
model=OpenAIHostedMultiAgentModel(
model="gpt-5.6-sol",
config={"max_concurrent_subagents": 3},
),
tools=[get_proposal],
)
def log_hosted_event(event: object) -> None:
if getattr(event, "type", None) != "response.output_item.done":
return
item = getattr(event, "item", None)
item_type = item.get("type") if isinstance(item, Mapping) else getattr(item, "type", None)
metadata = get_hosted_agent_metadata(item)
is_hosted_item = item_type in {
"agent_message",
"multi_agent_call",
"multi_agent_call_output",
}
is_subagent_message = (
item_type == "message" and metadata is not None and metadata.agent_name != "/root"
)
if is_hosted_item or is_subagent_message:
caller = metadata.agent_name if metadata else "unknown"
print(f"hosted item type={item_type} agent={caller}")
async def run_nonstreamed() -> None:
result = await Runner.run(build_agent(), "Compare proposal alpha and proposal beta.")
print(f"\nFinal response:\n{result.final_output}")
async def run_streamed() -> None:
result = Runner.run_streamed(build_agent(), "Compare proposal alpha and proposal beta.")
async for event in result.stream_events():
if event.type == "raw_response_event":
log_hosted_event(event.data)
print(f"\nFinal response:\n{result.final_output}")
async def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--mode", choices=("nonstream", "stream"), default="nonstream")
args = parser.parse_args()
if args.mode == "stream":
await run_streamed()
else:
await run_nonstreamed()
if __name__ == "__main__":
asyncio.run(main())