Complex handoffs

Complex handoffs

Project: examples/complex-handoffs. One agent, several kinds of handoff, each enforced by what is rendered.

Into a skill, by code. The skill arrives as the result of the tool that opened it:

const router = useRouter();

<Tool
  name="verify_customer"
  description="Look the caller up by their customer number."
  schema={z.object({ customerNumber: z.string() })}
  onSubmit={({ customerNumber }) => {
    const customer = CUSTOMERS[customerNumber];
    if (!customer) return { ok: false, message: "No customer has that number." };
    setCustomer(customer);
    router.push("/contract");
    return { ok: true };
  }}
/>

To a skill with its own voice. Props on the link apply while that skill is active, and a store carries the customer across:

<Skill path="/cancellation" description="Use when the caller wants to cancel." tts={kugelaudio.tts({ language: "en", voice: 1072 })}>
  Cancellation
</Skill>

To a person, with a note, and a fallback. Curb has no whisper: the person who picks up hears nothing from the agent, and sees the number of the line that dials them, not the caller’s. So send the note ahead of the transfer. A failed transfer renders the callback tool:

const transfer = useTransferCall();
const send = useSend();

<Tool
  name="hand_to_advisor"
  description="Record why the caller needs a person, then put them through."
  schema={z.object({ summary: z.string().describe("What the caller needs, in one sentence.") })}
  onSubmit={async ({ summary }) => {
    send.toHost("handoff.note", { customerId: customer?.id, summary });
    const { outcome } = await transfer({ to: "+493098765432", announce: "One moment, I am putting you through." });
    if (outcome === "answered") return { ok: true };
    setTransferFailed();
    return { ok: false, message: `The transfer ended as ${outcome}: nobody took the call.` };
  }}
/>

send.toHost puts the note on the call’s Data tab on KugelAudio, and on the events stream of your own host. With no host it is dropped with a warning. Neither reaches a person on a phone: to do that, call your own system from the tool (a ticket, a text message) before the transfer.

There is no agent-to-agent handoff between two deployed agents, other than a phone transfer to the other agent’s number.

Next steps