# Conversation States
[
  {
    "id": "1_greeting",
    "description": "Greet the caller and explain the verification process.",
    "instructions": [
      "Greet the caller warmly.",
      "Inform them about the need to collect personal information for their record."
    ],
    "examples": [
      "Good morning, this is the front desk administrator. I will assist you in verifying your details.",
      "Let us proceed with the verification. May I kindly have your first name? Please spell it out letter by letter for clarity."
    ],
    "transitions": [{
      "next_step": "2_get_first_name",
      "condition": "After greeting is complete."
    }]
  },
  {
    "id": "2_get_first_name",
    "description": "Ask for and confirm the caller's first name.",
    "instructions": [
      "Request: 'Could you please provide your first name?'",
      "Spell it out letter-by-letter back to the caller to confirm."
    ],
    "examples": [
      "May I have your first name, please?",
      "You spelled that as J-A-N-E, is that correct?"
    ],
    "transitions": [{
      "next_step": "3_get_last_name",
      "condition": "Once first name is confirmed."
    }]
  },
  {
    "id": "3_get_last_name",
    "description": "Ask for and confirm the caller's last name.",
    "instructions": [
      "Request: 'Thank you. Could you please provide your last name?'",
      "Spell it out letter-by-letter back to the caller to confirm."
    ],
    "examples": [
      "And your last name, please?",
      "Let me confirm: D-O-E, is that correct?"
    ],
    "transitions": [{
      "next_step": "4_next_steps",
      "condition": "Once last name is confirmed."
    }]
  },
  {
    "id": "4_next_steps",
    "description": "Attempt to verify the caller's information and proceed with next steps.",
    "instructions": [
      "Inform the caller that you will now attempt to verify their information.",
      "Call the 'authenticateUser' function with the provided details.",
      "Once verification is complete, transfer the caller to the tourGuide agent for further assistance."
    ],
    "examples": [
      "Thank you for providing your details. I will now verify your information.",
      "Attempting to authenticate your information now.",
      "I'll transfer you to our agent who can give you an overview of our facilities. Just to help demonstrate different agent personalities, she's instructed to act a little crabby."
    ],
    "transitions": [{
      "next_step": "transferAgents",
      "condition": "Once verification is complete, transfer to tourGuide agent."
    }]
  }
]
```

Instead of writing this out by hand, you can also check out this Voice Agent
Metaprompter or copy the metaprompt and use it directly.

### Handle agent handoff

In order to keep your agent focused on a single task, you can provide the agent
with the ability to transfer or handoff to another specialized agent. You can do
this by providing the agent with a function tool to initiate the transfer. This
tool should have information on when to use it for a handoff.

If you are using the OpenAI Agents SDK for TypeScript, you can define any agent
as a potential handoff to another agent.

```typescript
import { RealtimeAgent } from "@openai/agents/realtime";

const productSpecialist = new RealtimeAgent({
  name: "Product Specialist",
  instructions:
    "You are a product specialist. You are responsible for answering questions about our products.",
});

const triageAgent = new RealtimeAgent({
  name: "Triage Agent",
  instructions:
    "You are a customer service frontline agent. You are responsible for triaging calls to the appropriate agent.",
  tools: [productSpecialist],
});
```

The SDK will automatically facilitate the handoff between the agents for you.

Alternatively if you are building your own voice agent, here is an example of
such a tool definition:

```js
const tool = {
  type: "function",
  function: {
    name: "transferAgents",
    description: `
Triggers a transfer of the user to a more specialized agent.
Calls escalate to a more specialized LLM agent or to a human agent, with additional context.
Only call this function if one of the available agents is appropriate. Don't transfer to your own agent type.

Let the user know you're about to transfer them before doing so.

Available Agents:
- returns_agent
- product_specialist_agent
  `.trim(),
    parameters: {
      type: "object",
      properties: {
        rationale_for_transfer: {
          type: "string",
          description: "The reasoning why this transfer is needed.",
        },
        conversation_context: {
          type: "string",
          description:
            "Relevant context from the conversation that will help the recipient perform the correct action.",
        },
        destination_agent: {
          type: "string",
          description:
            "The more specialized destination_agent that should handle the user's intended request.",
          enum: ["returns_agent", "product_specialist_agent"],
        },
      },
    },
  },
};
```

Once the agent calls that tool you can then use the `session.update` event of
the Realtime API to update the configuration of the session to use the
instructions and tools available to the specialized agent.

### Extend your agent with specialized models

![Diagram showing the speech-to-speech model calling other agents as tools](https://cdn.openai.com/API/docs/diagram-speech-to-speech-agent-tools.png)

While the speech-to-speech model is useful for conversational use cases, there
might be use cases where you need a specific model to handle the task like
having o3 validate a return request against a detailed return policy.

In that case you can expose your text-based agent using your preferred model as
a function tool call that your agent can send specific requests to.

If you are using the OpenAI Agents SDK for TypeScript, you can give a
`RealtimeAgent` a `tool` that will trigger the specialized agent on your server.

```typescript
import { RealtimeAgent, tool } from "@openai/agents/realtime";
import { z } from "zod";

const supervisorAgent = tool({
  name: "supervisorAgent",
  description: "Passes a case to your supervisor for approval.",
  parameters: z.object({
    caseDetails: z.string(),
  }),
  execute: async ({ caseDetails }, details) => {
    const history = details.context.history;
    const response = await fetch("/request/to/your/specialized/agent", {
      method: "POST",
      body: JSON.stringify({
        caseDetails,
        history,
      }),
    });
    return response.text();
  },
});

const returnsAgent = new RealtimeAgent({
  name: "Returns Agent",
  instructions:
    "You are a returns agent. You are responsible for handling return requests. Always check with your supervisor before making a decision.",
  tools: [supervisorAgent],
});
```