This repository demonstrates a production-ready multi-agent AI system with intelligent handoff, built using the OpenAI Agents SDK.
At the core of the system is a Reception Agent that understands user intent, applies input/output guardrails, and routes the request to the most suitable specialized agent similar to a real-world receptionist.
Note
Pixelhouse is only an example use case.
The system architecture itself is generic, reusable, and not tied to any specific business domain.
- Node.js
- OpenAI Agents SDK
- Zod (schema validation)
- dotenv
- fs/promises (persistence)
├── 📁 agent
│ ├── 📄 agent.service.ts # Main agent
│ ├── 📄 booking.agent.ts # Booking agent
│ ├── 📄 checkVacancy.agent.ts # Team managing agent
│ ├── 📄 refund.agent.ts # Manages refund
│ └── 📄 sales.agent.ts # Sales agent
├── 📁 data
│ └── 📄 data.ts # Dummy data
├── 📁 guardrails
│ ├── 📄 agentRes.guardrails.ts # Output Guardrails
│ └── 📄 userInput.guardrails.ts # Input Guardrails
├── 📁 tool
│ └── 📄 tools.ts # Agent Tools
└── 📄 types.ts # TS types
- Multi-agent architecture
- Central Reception Agent
- Automatic intent-based handoff
- Conversation Threads (Stateful Conversations)
- Input guardrails for safety & validation
- Output guardrails for controlled responses
- Modular and scalable design
This multi-agent system supports conversation threads so the assistant can remember context across multiple user messages (like a real receptionist).
Instead of treating every message as a new request, the system keeps the same thread/session id so agents can:
- Continue the same conversation
- Remember previously shared details (user id, booking info, refund reason, etc.)
- Avoid asking repeated questions
- Maintain smooth handoff between agents
User Message
↓
Thread ID (same session)
↓
Reception Agent
↓
Agent Handoff (Sales / Refund / Vacancy / Booking)
↓
Response Stored in Same Thread
async function runAgent(query: string) {
const result = await run(mainAgent, query, {
conversationId : process.env.CONV_KEY
});
console.log(result.finalOutput);
// console.log(result.history);
}- Understand the user’s intent
- Apply input guardrails
- Select the appropriate agent
- Hand off the task
- Apply output guardrails before responding
| Agent | Description |
|---|---|
| Sales Agent | Handles queries related to plans, pricing, and first-time customer questions |
| Refund Agent | Initiates refunds, collects user details, and records cancellation reasons |
| Check Team Vacancy Agent | Checks team availability for scheduling shoots |
| Booking Agent | Books shoots and assigns team members based on availability |
User Query
↓
Input Guardrails
↓
Reception Agent
↓ (Intent Detection)
---------------------------------
| Sales | Refund | Vacancy | Booking |
---------------------------------
↓
Output Guardrails
↓
Final Response
- Scalable and modular
- Clear separation of concerns
- Real-world workflow simulation
- Built-in safety with guardrails
- Easy to extend with new agents
async function runAgent(query: string) {
const result = await run(mainAgent, query);
console.log(result.finalOutput);
}
const query =
"Hey there, my name is Asad Hussain with userid #2408 and I want a refund as the shoot was cancelled";
-
“What plans do you offer?” → Sales Agent
-
“I want a refund for my last shoot” → Refund Agent
-
“Is your team available this weekend?” → Check Team Vacancy Agent
-
“Book a shoot for next Friday” → Booking Agent
- Install dotenv
npm i dotenv
- Create a .env file in the root directory:
OPENAI_API_KEY=your_openai_api_key = add your api key
I am open to discussing opportunities and collaborations. Connect with me:
- Email: techie.asad.dev@gmail.com
- GitHub: @asad-bot07
- LinkedIn: Asad Hussain
Explore my work and professional journey: https://asadtechdev.vercel.app