# /// script # requires-python = ">=3.12" # dependencies = ["openai==3.24.0"] # /// """Replay a group chat one message at a time; Ampersand calls send_message or pass after each.""" import os import time from openai import OpenAI TOOLS = [ { "type": "function", "name": "send_message", "description": "Send one message to the group chat. " "Plain text outside this tool is not delivered.", "parameters": { "type": "object", "properties": {"content": {"type": "string"}}, "required": ["content"], }, }, { "type": "function", "name": "pass", "description": "Yield without a visible message when no useful action is available now. " "Call pass on its own.", "parameters": {"type": "object", "properties": {}, "required": []}, }, ] CHAT = [ ("Sam", "Heads up, I'm out Friday, driving to my sister's."), ("Alex", "Have a good trip!"), ("Maya", "Let's do the launch rehearsal Friday at 10 with all three of us."), ] def message(sender, text, channel="group"): return { "role": "user", "content": [{"type": "input_text", "text": text}], "metadata": {"sender": sender, "channel": channel, "timestamp": int(time.time())}, } def next_decision(stream, previous_call_id=None): """Read events until Ampersand calls send_message or pass.""" for event in stream: if event.type == "agent.session.requires_action": call = event.session.required_actions[0] if call.call_id != previous_call_id: return event.session.id, call if event.type in {"agent.session.failed", "agent.session.turn.failed"}: raise RuntimeError(f"Ampersand stopped: {event.type}") raise RuntimeError("The stream closed before Ampersand decided.") def show(sender, text, call): print(f"\n{sender}: {text}", flush=True) if call.name == "send_message": print(f"Ampersand: {call.arguments['content']}", flush=True) else: print(" (Ampersand stays quiet)", flush=True) roster = message( "environment", "Group members: [Maya] Maya, [Alex] Alex, [Sam] Sam.\n" "You are Ampersand, the AI assistant in this chat.", channel="setup", ) nudge = message("environment", "Act if useful; otherwise pass.", channel="setup") with OpenAI( base_url=os.environ["AMPERSAND_BASE_URL"], api_key=os.environ["AMPERSAND_API_KEY"], max_retries=0, ) as client: (sender, text), *later = CHAT with client.beta.agents.sessions.create( agent={ "model": os.environ["AMPERSAND_MODEL"], "tools": TOOLS, "ampersand": {"allow_silent_completion": False}, }, environment={"type": "none"}, input=[roster, message(sender, text), nudge], stream=True, ) as stream: session_id, call = next_decision(stream) show(sender, text, call) for sender, text in later: with client.beta.agents.sessions.events.stream(session_id) as stream: client.beta.agents.sessions.events.create( session_id, events=[ { "type": "agent.session.input.tool_result", "turn_id": call.turn_id, "call_id": call.call_id, "success": True, "output": "Message sent." if call.name == "send_message" else "Passing.", }, {"type": "agent.session.input.message", "input": [message(sender, text)]}, ], ) session_id, call = next_decision(stream, previous_call_id=call.call_id) show(sender, text, call)