|
1 | 1 | # Realtime API Agents Demo
|
2 | 2 |
|
3 |
| -This is a simple demonstration of more advanced, agentic patterns built on top of the Realtime API. In particular, this demonstrates: |
4 |
| -- Sequential agent handoffs according to a defined agent graph (taking inspiration from [OpenAI Swarm](https://github.com/openai/swarm)) |
5 |
| -- Background escalation to more intelligent models like o4-mini for high-stakes decisions |
6 |
| -- Prompting models to follow a state machine, for example to accurately collect things like names and phone numbers with confirmation character by character to authenticate a user. |
7 |
| - |
8 |
| -Here's a quick [demo video](https://x.com/OpenAIDevs/status/1880306081517432936) if you'd like a walkthrough. You should be able to use this repo to prototype your own multi-agent realtime voice app in less than 20 minutes! |
9 |
| - |
10 |
| - |
| 3 | +This is a demonstration of more advanced patterns for voice agents, using the OpenAI Realtime API. There are two main patterns demonstrated: |
| 4 | +1. **Chat-Supervisor:** A realtime-based chat agent interacts with the user and handles basic tasks, while a more intelligent, text-based supervisor model (e.g., `gpt-4.1`) is used extensively for tool calls and more complex responses. This approach provides an easy onramp and high-quality answers, with a small increase in latency. |
| 5 | +2. **Sequential Handoff:** Specialized agents (powered by realtime api) transfer the user between them to handle specific user intents. This is great for customer service, where user intents can be handled sequentially by specialist models that excel in a specific domains. This helps avoid the model having all instructions and tools in a single agent, which can degrade performance. |
11 | 6 |
|
12 | 7 | ## Setup
|
13 | 8 |
|
14 |
| -- This is a Next.js typescript app |
15 |
| -- Install dependencies with `npm i` |
16 |
| -- Add your `OPENAI_API_KEY` to your env. Either add it to your `.bash_profile` or equivalent file, or copy `.env.sample` to `.env` and add it there. |
| 9 | +- This is a Next.js typescript app. Install dependencies with `npm i`. |
| 10 | +- Add your `OPENAI_API_KEY` to your env. Either add it to your `.bash_profile` or equivalent, or copy `.env.sample` to `.env` and add it there. |
17 | 11 | - Start the server with `npm run dev`
|
18 |
| -- Open your browser to [http://localhost:3000](http://localhost:3000) to see the app. It should automatically connect to the `simpleExample` Agent Set. |
| 12 | +- Open your browser to [http://localhost:3000](http://localhost:3000). It should default to the `chatSupervisor` Agent Config. |
| 13 | +- You can change examples via the "Scenario" dropdown in the top right. |
| 14 | + |
| 15 | +# 1. Chat-Supervisor |
| 16 | + |
| 17 | +This is demonstrated in the [chatSupervisor](src/app/agentConfigs/chatSupervisor/index.ts) Agent Config. The chat agent uses the realtime model to converse with the user and handle basic tasks, like greeting the user, casual conversation, and collecting information, and a more intelligent, text-based supervisor model (e.g. `gpt-4.1`) is used extensively to handle tool calls and more challenging responses. You can control the decision boundary by "opting in" specific tasks to the chat agent as desired. |
| 18 | + |
| 19 | +## Example |
| 20 | + |
| 21 | +*In this screenshot, note the immediate response to collect the phone number, and the deferral to the supervisor agent to handle the tool call and formulate the response. Note that there was only ~2s between the end of "give me a moment to check on that." and the start of the "Thanks for waiting. Your last bill..." message.* |
| 22 | + |
| 23 | +## Schematic |
| 24 | +```mermaid |
| 25 | +sequenceDiagram |
| 26 | + participant User |
| 27 | + participant ChatAgent as Chat Agent<br/>(gpt-4o-realtime-mini) |
| 28 | + participant Supervisor as Supervisor Agent<br/>(gpt-4.1) |
| 29 | + participant Tool as Tool |
| 30 | +
|
| 31 | + alt Basic chat or info collection |
| 32 | + User->>ChatAgent: User message |
| 33 | + ChatAgent->>User: Responds directly |
| 34 | + else Requires higher intelligence and/or tool call |
| 35 | + User->>ChatAgent: User message |
| 36 | + ChatAgent->>User: "Let me think" |
| 37 | + ChatAgent->>Supervisor: Forwards message/context |
| 38 | + alt Tool call needed |
| 39 | + Supervisor->>Tool: Calls tool |
| 40 | + Tool->>Supervisor: Returns result |
| 41 | + end |
| 42 | + Supervisor->>ChatAgent: Returns response |
| 43 | + ChatAgent->>User: Delivers response |
| 44 | + end |
| 45 | +``` |
| 46 | + |
| 47 | +## Benefits |
| 48 | +- **Simpler onboarding.** If you already have a performant text-based chat agent, you can give that same prompt and set of tools to the supervisor agent, and make some tweaks to the chat agent prompt, you'll have a natural voice agent that will perform on par with your text agent. |
| 49 | +- **Simple ramp to a full realtime agent**: Rather than switching your whole agent to the realtime api, you can move one task at a time, taking time to validate and build trust for each before deploying to production. |
| 50 | +- **High intelligence**: You benefit from the high intelligence, excellent tool calling and instruction following of models like `gpt-4.1` in your voice agents. |
| 51 | +- **Lower cost**: If your chat agent is only being used for basic tasks, you can use the realtime-mini model, which, even when combined with GPT-4.1, should be cheaper than using the full 4o-realtime model. |
| 52 | +- **User experience**: It's a more natural conversational experience than using a stitched model architecture, where response latency is often 1.5s or longer after a user has finished speaking. In this architecture, the model responds to the user right away, even if it has to lean on the supervisor agent. |
| 53 | + - However, more assistant responses will start with "Let me think", rather than responding immediately with the full response. |
| 54 | + |
| 55 | +## Modifying for your own agent |
| 56 | +1. Update [supervisorAgent](src/app/agentConfigs/chatSupervisorDemo/supervisorAgent.ts). |
| 57 | + a. Add your existing text agent prompt and tools if you already have them. This should contain the "meat" of your voice agent logic and be very specific with what it should/shouldn't do and how exactly it should respond. Add this information below `==== Domain-Specific Agent Instructions ====`. |
| 58 | + b. You should likely update this prompt to be more appropriate for voice, for example with instructions to be concise and avoiding long lists of items. |
| 59 | +2. Update [chatAgent](src/app/agentConfigs/chatSupervisor/index.ts). |
| 60 | + a. Customize the chatAgent instructions with your own tone, greeting, etc. |
| 61 | + b. Add your tool definitions to `chatAgentInstructions`. We recommend a brief yaml description rather than json to ensure the model doesn't get confused and try calling the tool directly. |
| 62 | + c. You can modify the decision boundary by adding new items to the `# Allow List of Permitted Actions` section. |
| 63 | +3. To reduce cost, try using `gpt-4o-mini-realtime` for the chatAgent and/or `gpt-4.1-mini` for the supervisor model. To maximize intelligence on particularly difficult or high-stakes tasks, consider trading off latency and adding chain-of-thought to your supervisor prompt, or using an additional reasoning model-based supervisor that uses `o4-mini`. |
| 64 | + |
| 65 | +# 2. Sequential Handoffs |
| 66 | + |
| 67 | +This pattern is inspired by [OpenAI Swarm](https://github.com/openai/swarm) and involves the sequential handoff of a user between specialized agents. Handoffs are decided by the model and coordinated via tool calls, and possible handoffs are defined explicitly in an agent graph. A handoff triggers a session.update event with new instructions and tools. This pattern is effective for handling a variety of user intents with specialist agents, each of which might have long instructions and numerous tools. |
| 68 | + |
| 69 | +Here's a [video walkthrough](https://x.com/OpenAIDevs/status/1880306081517432936) showing how it works. You should be able to use this repo to prototype your own multi-agent realtime voice app in less than 20 minutes! |
| 70 | + |
| 71 | + |
| 72 | +*In this simple example, the user is transferred from a greeter agent to a haiku agent. See below for the simple, full configuration of this flow.* |
19 | 73 |
|
20 |
| -## Configuring Agents |
21 | 74 | Configuration in `src/app/agentConfigs/simpleExample.ts`
|
22 | 75 | ```javascript
|
23 | 76 | import { AgentConfig } from "@/app/types";
|
@@ -46,12 +99,40 @@ const agents = injectTransferTools([greeter, haikuWriter]);
|
46 | 99 |
|
47 | 100 | export default agents;
|
48 | 101 | ```
|
| 102 | +## CustomerServiceRetail Flow |
49 | 103 |
|
50 |
| -This fully specifies the agent set that was used in the interaction shown in the screenshot above. |
| 104 | +This is a more complex, representative implementation that illustrates a customer service flow, with the following features: |
| 105 | +- A more complex agent graph with agents for user authentication, returns, sales, and a placeholder human agent for escalations. |
| 106 | +- An escalation by the [returns](https://github.com/openai/openai-realtime-agents/blob/60f4effc50a539b19b2f1fa4c38846086b58c295/src/app/agentConfigs/customerServiceRetail/returns.ts#L233) agent to `o4-mini` to validate and initiate a return, as an example high-stakes decision, using a similar pattern to the above. |
| 107 | +- Prompting models to follow a state machine, for example to accurately collect things like names and phone numbers with confirmation character by character to authenticate a user. |
| 108 | + - To test this flow, say that you'd like to return your snowboard and go through the necessary prompts! |
51 | 109 |
|
52 |
| -### Sequence Diagram of CustomerServiceRetail Flow |
| 110 | +Configuration in [src/app/agentConfigs/customerServiceRetail/index.ts](src/app/agentConfigs/customerServiceRetail/index.ts). |
| 111 | +```javascript |
| 112 | +import authentication from "./authentication"; |
| 113 | +import returns from "./returns"; |
| 114 | +import sales from "./sales"; |
| 115 | +import simulatedHuman from "./simulatedHuman"; |
| 116 | +import { injectTransferTools } from "../utils"; |
| 117 | + |
| 118 | +authentication.downstreamAgents = [returns, sales, simulatedHuman]; |
| 119 | +returns.downstreamAgents = [authentication, sales, simulatedHuman]; |
| 120 | +sales.downstreamAgents = [authentication, returns, simulatedHuman]; |
| 121 | +simulatedHuman.downstreamAgents = [authentication, returns, sales]; |
| 122 | + |
| 123 | +const agents = injectTransferTools([ |
| 124 | + authentication, |
| 125 | + returns, |
| 126 | + sales, |
| 127 | + simulatedHuman, |
| 128 | +]); |
53 | 129 |
|
54 |
| -This diagram illustrates the interaction flow defined in `src/app/agentConfigs/customerServiceRetail/`. |
| 130 | +export default agents; |
| 131 | +``` |
| 132 | + |
| 133 | +## Schematic |
| 134 | + |
| 135 | +This diagram illustrates a more advanced interaction flow defined in `src/app/agentConfigs/customerServiceRetail/`. |
55 | 136 |
|
56 | 137 | <details>
|
57 | 138 | <summary><strong>Show CustomerServiceRetail Flow Diagram</strong></summary>
|
@@ -108,28 +189,25 @@ sequenceDiagram
|
108 | 189 |
|
109 | 190 | </details>
|
110 | 191 |
|
| 192 | +# Other Info |
| 193 | +## Next Steps |
| 194 | +- You can copy these templates to make your own multi-agent voice app! Once you make a new agent set config, add it to `src/app/agentConfigs/index.ts` and you should be able to select it in the UI in the "Scenario" dropdown menu. |
| 195 | +- Each agentConfig can define instructions, tools, and toolLogic. By default all tool calls simply return `True`, unless you define the toolLogic, which will run your specific tool logic and return an object to the conversation (e.g. for retrieved RAG context). |
| 196 | +- If you want help creating your own prompt using the conventions shown in customerServiceRetail, including defining a state machine, we've included a metaprompt [here](src/app/agentConfigs/voiceAgentMetaprompt.txt), or you can use our [Voice Agent Metaprompter GPT](https://chatgpt.com/g/g-678865c9fb5c81918fa28699735dd08e-voice-agent-metaprompt-gpt) |
111 | 197 |
|
112 |
| -### Next steps |
113 |
| -- Check out the configs in `src/app/agentConfigs`. The example above is a minimal demo that illustrates the core concepts. |
114 |
| -- [frontDeskAuthentication](src/app/agentConfigs/frontDeskAuthentication) Guides the user through a step-by-step authentication flow, confirming each value character-by-character, authenticates the user with a tool call, and then transfers to another agent. Note that the second agent is intentionally "bored" to show how to prompt for personality and tone. |
115 |
| -- [customerServiceRetail](src/app/agentConfigs/customerServiceRetail) Also guides through an authentication flow, reads a long offer from a canned script verbatim, and then walks through a complex return flow which requires looking up orders and policies, gathering user context, and checking with `o4-mini` to ensure the return is eligible. To test this flow, say that you'd like to return your snowboard and go through the necessary prompts! |
116 |
| - |
117 |
| -### Defining your own agents |
118 |
| -- You can copy these to make your own multi-agent voice app! Once you make a new agent set config, add it to `src/app/agentConfigs/index.ts` and you should be able to select it in the UI in the "Scenario" dropdown menu. |
119 |
| -- To see how to define tools and toolLogic, including a background LLM call, see [src/app/agentConfigs/customerServiceRetail/returns.ts](src/app/agentConfigs/customerServiceRetail/returns.ts) |
120 |
| -- To see how to define a detailed personality and tone, and use a prompt state machine to collect user information step by step, see [src/app/agentConfigs/frontDeskAuthentication/authentication.ts](src/app/agentConfigs/frontDeskAuthentication/authentication.ts) |
121 |
| -- To see how to wire up Agents into a single Agent Set, see [src/app/agentConfigs/frontDeskAuthentication/index.ts](src/app/agentConfigs/frontDeskAuthentication/index.ts) |
122 |
| -- If you want help creating your own prompt using these conventions, we've included a metaprompt [here](src/app/agentConfigs/voiceAgentMetaprompt.txt), or you can use our [Voice Agent Metaprompter GPT](https://chatgpt.com/g/g-678865c9fb5c81918fa28699735dd08e-voice-agent-metaprompt-gpt) |
| 198 | +## Output Guardrails |
| 199 | +Assistant messages are checked for safety and compliance using a guardrail function before being finalized in the transcript. This is implemented in [`src/app/hooks/useHandleServerEvent.ts`](src/app/hooks/useHandleServerEvent.ts) as the `processGuardrail` function, which is invoked on each assistant message (after every 5 incremental words received) to run a moderation/classification check. You can review or customize this logic by editing the `processGuardrail` function definition and its invocation inside `useHandleServerEvent`. |
123 | 200 |
|
124 |
| -### Customizing Output Guardrails |
125 |
| -Assistant messages are checked for safety and compliance using a guardrail function before being finalized in the transcript. This is implemented in [`src/app/hooks/useHandleServerEvent.ts`](src/app/hooks/useHandleServerEvent.ts) as the `processGuardrail` function, which is invoked on each assistant message to run a moderation/classification check. You can review or customize this logic by editing the `processGuardrail` function definition and its invocation inside `useHandleServerEvent`. |
126 |
| - |
127 |
| -## UI |
| 201 | +## Navigating the UI |
128 | 202 | - You can select agent scenarios in the Scenario dropdown, and automatically switch to a specific agent with the Agent dropdown.
|
129 | 203 | - The conversation transcript is on the left, including tool calls, tool call responses, and agent changes. Click to expand non-message elements.
|
130 | 204 | - The event log is on the right, showing both client and server events. Click to see the full payload.
|
131 | 205 | - On the bottom, you can disconnect, toggle between automated voice-activity detection or PTT, turn off audio playback, and toggle logs.
|
132 | 206 |
|
133 |
| -## Core Contributors |
| 207 | +## Pull Requests |
| 208 | + |
| 209 | +Feel free to open an issue or pull request and we'll do our best to review it. The spirit of this repo is to demonstrate the core logic for new agentic flows; PRs that go beyond this core scope will likely not be merged. |
| 210 | + |
| 211 | +# Core Contributors |
134 | 212 | - Noah MacCallum - [noahmacca](https://x.com/noahmacca)
|
135 | 213 | - Ilan Bigio - [ibigio](https://github.com/ibigio)
|
0 commit comments