I understand that tasks & workflows are not av...
# ask-ai
c
I understand that tasks & workflows are not available in typescript sdk for livekit. Can you give a minimal example of how to do an agent workflow with a series of steps in the latest version of typescript sdk of livekit?
t
Thanks for reaching out, Jatin. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about a minimal TypeScript example for an agent workflow (since tasks & workflows aren’t available in the TypeScript SDK). Below is a concise, minimal pattern you can use: implement each step as an agent, keep shared state on the session, and use handoffs to move between steps.
Copy code
import { voice, llm, z } from "@livekit/agents";

// Base agent with shared behavior
class StepAgent extends voice.Agent {
  constructor(instructions: string) {
    super({ instructions });
  }
}

// Step 1: collect name
class GetNameAgent extends StepAgent {
  constructor() {
    super("Collect the user's name.");
  }

  async onEnter() {
    this.session.generateReply({ instructions: "Please tell me your name." });
  }

  @llm.tool({
    description: "Record user's name",
    parameters: z.object({ name: z.string() }),
  })
  async recordName({ name }: { name: string }) {
    this.session.userData = { ...(this.session.userData || {}), name };
    return llm.handoff({
      agent: new GetEmailAgent(),
      returns: "Name recorded, handing off to email step.",
    });
  }
}

// Step 2: collect email
class GetEmailAgent extends StepAgent {
  constructor() {
    super("Collect the user's email.");
  }

  async onEnter() {
    const name = (this.session.userData as any)?.name ?? "there";
    this.session.generateReply({
      instructions: `Thanks ${name}. What is your email address?`,
    });
  }

  @llm.tool({
    description: "Record user's email",
    parameters: z.object({ email: z.string().email() }),
  })
  async recordEmail({ email }: { email: string }) {
    this.session.userData = { ...(this.session.userData || {}), email };
    this.session.generateReply({ instructions: "Thanks — we have your info." });
    // Optionally finish or shutdown the session
    // this.session.shutdown();
  }
}

// Entry: start the workflow with the first agent
export default defineAgent({
  entry: async (ctx: any) => {
    const session = new voice.AgentSession({
      vad: ctx.proc.userData.vad,
      stt: /* your STT instance */,
      llm: /* your LLM instance */,
      tts: /* your TTS instance */,
    });

    await session.start({
      room: ctx.room,
      agent: new GetNameAgent(),
      userData: {}, // initialize shared state
    });
  },
});
Key points: • Use
session.userData
to persist state across agent handoffs. • Use
llm.handoff()
to move control to the next step/agent. • Each step is one agent with its own
onEnter
prompt and tools to capture data. If you want, I can: • Show a conditional handoff example (skip steps based on input), • Convert this to a simpler callback-only flow (no decorators/tools), • Or adapt it to your actual STT/LLM/TTS providers — which one are you using? Sources: Agents Framework | livekit/livekit_composite | DeepWiki | Agents and handoffs | LiveKit docs