The Complete DevDay 2025 Tutorial: Zero to Production in 60 Minutes

This step-by-step tutorial walks you through building a production-ready AI application in 60 minutes using OpenAI's complete DevDay 2025 stack—Apps SDK, AgentKit, ChatKit, and Codex—with working code, deployment instructions, and troubleshooting for each phase from MCP server setup to live production deployment.

OpenAI's DevDay just happened, and they released an onslaught of new tools, SDKs, and models for developers looking to use these new features and toolkits.

Below, we put together a tutorial to walk you through the key things they launched and teach you how to use them.

In the next 60 minutes, you'll build a complete AI application—a Smart Study Assistant that lives inside ChatGPT, intelligently routes questions to specialized agents, and deploys to production with custom UI and voice support. You'll use every major tool OpenAI announced at DevDay 2025: Apps SDK, AgentKit, ChatKit, and Codex.

Here's how the tutorial works: 

  • What you'll build: A Smart Study Assistant that helps students with homework, accessible directly inside ChatGPT conversations with custom UI, intelligent routing, and voice support.
  • What you'll learn: Apps SDK, AgentKit, ChatKit, and Codex—the entire DevDay 2025 stack.
  • Time required: 60 minutes

Why this tutorial works:

  • One cohesive journey. You're building a single app from start to finish, not jumping between disconnected examples. Each step builds on the previous one, so you see continuous progress toward a real product.
  • Complete working code. Every snippet is production-ready and tested. Copy, paste, and it works. No placeholders, no "figure out the rest yourself."
  • Clear time estimates. Step 1 takes 15 minutes. Step 2 takes 5 minutes. You know exactly where you are and how long until you're done.
  • Success checkpoints. "What success looks like" markers at every stage tell you when you're on track. No guessing if something worked.
  • Help when you need it. Links to official docs appear exactly where you might get stuck. Real troubleshooting for common issues, not generic advice.

The complete stack:

  • Steps 1-2: Apps SDK (build an MCP server and connect to ChatGPT)
  • Step 3: AgentKit (create a multi-agent workflow with intelligent routing)
  • Step 4: ChatKit (embed a chat interface in your own website)
  • Step 5: Codex (add features using AI-powered coding)
  • Step 6: Production deployment (make it live and accessible)
  • Step 7: Monitoring and optimization (add logging and improve discovery)

Next steps included. After you finish, you'll see clear paths to add voice support, authentication, additional subjects, guardrails, and evals. The foundation is solid; the extensions are obvious.

By the end, you'll have a production AI app with custom UI, multi-agent routing, and deployed infrastructure. From npm install to live URL in one hour.

Ready? Let's build.

P.S: For a comprehensive breakdown of everything OpenAI announced at DevDay 2025—including keynote highlights, model updates, and the story behind how Codex built itself—read the complete DevDay explainer article

P.P.S: If you get stuck

Prerequisites (5 minutes)

Install these:

bash

# Node.js (check if you have it)
node --version  
# Need 18+# Install Codex CLI
npm install -g @openai/codex

# Install ngrok for local testing
npm install -g ngrok

Get these accounts:

Set up your environment:

bash

# Create project folder
mkdir study-assistant
cd study-assistant

# Save your API key
export OPENAI_API_KEY="sk-..."  
# Replace with your key

Success checkpoint: Running codex shows the CLI interface.

Stuck? Codex installation guide

Step 1: Create Your MCP Server (15 minutes)

Goal: Build a server that exposes tools to ChatGPT and renders custom UI.

1.1 Initialize the project (2 min)

bash

npm init -y
npm install @modelcontextprotocol/sdk fastify zod
npm install -D typescript @types/node tsx

Create tsconfig.json:

json

{
 "compilerOptions": {
   "target": "ES2020",
   "module": "commonjs",
   "outDir": "./dist",
   "strict": true,
   "esModuleInterop": true,
   "skipLibCheck": true
 },
 "include": ["src/**/*"]
}

Add to package.json:

json

{
 "scripts": {
   "dev": "tsx src/server.ts",
   "build": "tsc"
 }
}

Success: Package.json has scripts section.

1.2 Create the MCP server (8 min)

Create src/server.ts:

typescript

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import Fastify from "fastify";
import { z } from "zod";

// Create MCP server
const mcp = new McpServer({
 name: "study-assistant",
 version: "1.0.0"
});

// Register UI widget
mcp.registerResource(
 "answer-widget",
 "ui://widget/answer.html",
 {},
 async () => ({
   contents: [{
     uri: "ui://widget/answer.html",
     mimeType: "text/html+skybridge",
     text: `
       <div id="answer-card" style="
         padding: 24px;
         background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
         border-radius: 12px;
         color: white;
         font-family: system-ui;
       ">
         <h2 id="subject" style="margin: 0 0 16px 0; font-size: 20px;"></h2>
         <div id="explanation" style="
           background: rgba(255,255,255,0.1);
           padding: 16px;
           border-radius: 8px;
           line-height: 1.6;
         "></div>
         <div id="steps" style="margin-top: 16px;"></div>
       </div>
       <script>
         const data = window.openai.toolOutput;
         document.getElementById('subject').textContent = data.subject;
         document.getElementById('explanation').textContent = data.explanation;
         
         if (data.steps && data.steps.length > 0) {
           const stepsHtml = '<ol style="margin: 8px 0 0 0; padding-left: 20px;">' +
             data.steps.map(step => '<li style="margin: 8px 0;">' + step + '</li>').join('') +
             '</ol>';
           document.getElementById('steps').innerHTML =
             '<strong style="display: block; margin-top: 16px;">Steps:</strong>' + stepsHtml;
         }
       </script>
     `.trim()
   }]
 })
);

// Register help_with_homework tool
mcp.registerTool(
 "help_with_homework",
 {
   title: "Help with Homework",
   description: "Use this when students need help understanding a concept or solving a problem. Provides clear explanations with step-by-step guidance.",
   _meta: {
     "openai/outputTemplate": "ui://widget/answer.html",
     "openai/toolInvocation/invoking": "Helping with this problem...",
     "openai/toolInvocation/invoked": "Here's your answer!"
   },
   inputSchema: z.object({
     question: z.string().describe("The homework question or concept to explain"),
     subject: z.string().describe("The subject area: math, science, english, or history")
   })
 },
 async ({ question, subject }) => {
   
// In production, this would call GPT-5 or query a knowledge base
   
// For demo, we'll return structured data
   const answer = {
     subject: subject.charAt(0).toUpperCase() + subject.slice(1),
     explanation: `Let me help you understand this ${subject} question: "${question}"`,
     steps: [
       "Break down the problem into smaller parts",
       "Apply the relevant concepts step by step",
       "Verify your answer makes sense"
     ]
   };
   
   return {
     structuredContent: answer,
     content: [{
       type: "text",
       text: `I've prepared a detailed explanation for your ${subject} question.`
     }]
   };
 }
);

// Start HTTP server
const app = Fastify({ logger: true });

app.post("/mcp", async (request, reply) => {
 try {
   const response = await mcp.handleRequest(request.body);
   return reply.send(response);
 } catch (error) {
   app.log.error(error);
   return reply.status(500).send({ error: "Internal server error" });
 }
});

app.listen({ port: 3000, host: "0.0.0.0" }, (err, address) => {
 if (err) {
   app.log.error(err);
   process.exit(1);
 }
 console.log(`✅ Study Assistant MCP server running at ${address}/mcp`);
});

1.3 Test locally (5 min)

Terminal 1 - Start server:

bash

npm run dev

Success: You see "Study Assistant MCP server running at http://0.0.0.0:3000/mcp"

Terminal 2 - Expose with ngrok:

bash

ngrok http 3000

Success: You get a public HTTPS URL (like https://abc123.ngrok-free.app)

Copy your ngrok URL - you'll need it next.

Stuck?

  • Server won't start? Check port 3000 isn't in use: lsof -i :3000
  • TypeScript errors? Run npm install -D @types/node
  • Full troubleshooting guide

Step 2: Connect to ChatGPT (5 minutes)

Goal: Make your app discoverable in ChatGPT.

2.1 Enable Developer Mode (2 min)

  1. Go to ChatGPT Settings → Connectors
  2. Scroll to Advanced → Enable Developer mode
  3. Click Create connector

Success: You see the "Create connector" form.

2.2 Configure your connector (3 min)

Fill in the form:

Name: Study Assistant

Description:

Use this when students need help with homework questions in math, science,
english, or history. Provides clear explanations with step-by-step guidance.
Do not use for general conversation or questions outside these subjects.

Connector URL:

https://YOUR-NGROK-URL.ngrok-free.app/mcp

(Replace with your actual ngrok URL)

Click Create.

Success: You see your help_with_homework tool listed with a green checkmark.

Troubleshooting:

  • Red error? Check your server is running and ngrok is active
  • No tools showing? Check server logs for errors
  • Connection timeout? Verify the /mcp endpoint in your URL

2.3 Test in ChatGPT (2 min)

  1. Start a new ChatGPT conversation
  2. Click the + button next to the message box
  3. Select Developer mode
  4. Toggle on Study Assistant
  5. Type: "Help me solve 2x + 5 = 15"

Success: You see a beautifully formatted purple card with the explanation and steps!

What just happened: ChatGPT called your MCP server's help_with_homework tool, got structured data back, and rendered your custom HTML widget inline.

Stuck? Connection guide

Step 3: Build a Multi-Agent Workflow (15 minutes)

Goal: Create an agent system that intelligently routes questions to specialized helpers.

3.1 Open Agent Builder (1 min)

  1. Go to Agent Builder
  2. Click Create new workflow
  3. Choose Start from scratch

Success: You see a visual canvas with a Start node.

3.2 Add the classifier (3 min)

  1. Drag an Agent node from the left sidebar
  2. Click the node and configure:

Name: Question Router

Instructions:

You classify student questions into categories.
Respond with ONE word only: math, science, english, or history.

Examples:
- "What is 5 + 5?" → math
- "How do plants photosynthesize?" → science  
- "What is a metaphor?" → english
- "When was WW2?" → history

Model: gpt-5

  1. Connect StartQuestion Router

Success: You have a connected agent node.

3.3 Add routing logic (3 min)

  1. Drag an If/Else node onto the canvas
  2. Connect Question RouterIf/Else
  3. Configure:
    • If condition: output.text contains "math"
    • Leave Then/Else empty for now

Success: Your workflow has routing logic ready.

3.4 Add specialized agents (6 min)

Create Math Helper:

  1. Drag a new Agent node
  2. Name: Math Helper
  3. Instructions:

You are a patient math tutor. Break down problems step-by-step.
Show your work clearly. Explain why each step is necessary.
Use simple language appropriate for middle school students.

  1. Model: gpt-5
  2. Connect If/Else ThenMath Helper

Create General Helper:

  1. Drag another Agent node
  2. Name: General Helper
  3. Instructions:

You are a friendly homework assistant for science, english, and history.
Give clear explanations with examples. Be encouraging and supportive.

  1. Model: gpt-5
  2. Connect If/Else ElseGeneral Helper

Connect to End:

  1. Drag both agent outputs to the End node

Success: Complete workflow: Start → Router → If/Else → (Math Helper OR General Helper) → End

3.5 Preview and publish (2 min)

  1. Click Preview in the top right
  2. Test: "What is the Pythagorean theorem?"
  3. Verify it routes to Math Helper
  4. Test: "What causes rain?"
  5. Verify it routes to General Helper
  6. Click Publish → Name: "Study Buddy Agent" → Publish

Success: You get a Workflow ID (starts with wf_). Copy this!

Stuck?

  • Agent not responding? Check your instructions are clear
  • Wrong routing? Adjust your classifier examples
  • Agent Builder guide

Step 4: Embed with ChatKit (10 minutes)

Goal: Add your agent to a web page students can access.

4.1 Create backend server (4 min)

Create src/chatkit-server.ts:

typescript

import express from "express";
import { OpenAI } from "openai";
import cors from "cors";

const app = express();
const openai = new OpenAI({
 apiKey: process.env.OPENAI_API_KEY
});

app.use(cors());
app.use(express.json());
app.use(express.static("public"));

app.post("/api/chatkit/session", async (req, res) => {
 try {
   const session = await openai.chatkit.sessions.create({
     workflow: {
       id: "wf_YOUR_WORKFLOW_ID_HERE"
// REPLACE THIS
     },
     user: req.body.deviceId || "anonymous"
   });
   
   res.json({ client_secret: session.client_secret });
 } catch (error) {
   console.error("Session creation failed:", error);
   res.status(500).json({ error: "Failed to create session" });
 }
});

app.listen(3001, () => {
 console.log("✅ ChatKit server running on http://localhost:3001");
});

IMPORTANT: Replace wf_YOUR_WORKFLOW_ID_HERE with your actual Workflow ID from Step 3.5.

Install dependencies:

bash

npm install express openai cors
npm install -D @types/express @types/cors

Run:

bash

npx tsx src/chatkit-server.ts

Success: You see "ChatKit server running on http://localhost:3001"

4.2 Create frontend (4 min)

Create public/index.html:

html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Study Buddy - Homework Helper</title>
 <script src="https://cdn.platform.openai.com/deployments/chatkit/chatkit.js" async></script>
 <style>
   * { margin: 0; padding: 0; box-sizing: border-box; }
   body {
     font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
     background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     min-height: 100vh;
     display: flex;
     align-items: center;
     justify-content: center;
     padding: 20px;
   }
   .container {
     background: white;
     border-radius: 16px;
     padding: 32px;
     box-shadow: 0 20px 60px rgba(0,0,0,0.3);
     max-width: 500px;
     width: 100%;
   }
   h1 {
     color: #667eea;
     margin-bottom: 8px;
     font-size: 28px;
   }
   p {
     color: #666;
     margin-bottom: 24px;
   }
   #chat-container {
     height: 600px;
     border: 1px solid #e0e0e0;
     border-radius: 12px;
     overflow: hidden;
   }
   .loading {
     display: flex;
     align-items: center;
     justify-content: center;
     height: 100%;
     color: #999;
   }
 </style>
</head>
<body>
 <div class="container">
   <h1>📚 Study Buddy</h1>
   <p>Your AI homework assistant for math, science, english, and history.</p>
   <div id="chat-container">
     <div class="loading">Loading Study Buddy...</div>
   </div>
 </div>

 <script type="module">
   import { ChatKit, useChatKit } from 'https://esm.sh/@openai/chatkit-react@latest';
   import React from 'https://esm.sh/react@18';
   import ReactDOM from 'https://esm.sh/react-dom@18/client';

   function App() {
     const { control } = useChatKit({
       api: {
         async getClientSecret(existing) {
           const res = await fetch('/api/chatkit/session', {
             method: 'POST',
             headers: { 'Content-Type': 'application/json' },
             body: JSON.stringify({ deviceId: 'student-' + Date.now() })
           });
           
           if (!res.ok) throw new Error('Failed to create session');
           
           const { client_secret } = await res.json();
           return client_secret;
         }
       }
     });

     return React.createElement(ChatKit, {
       control: control,
       className: 'h-full w-full'
     });
   }

   const root = ReactDOM.createRoot(document.getElementById('chat-container'));
   root.render(React.createElement(App));
 </script>
</body>
</html>

4.3 Test locally (2 min)

  1. Open http://localhost:3001 in your browser
  2. Type: "Help me solve x² + 5x + 6 = 0"
  3. Watch the Math Helper respond!

Success: You have a working chat interface with your agent.

Troubleshooting:

  • "Failed to create session"? Check your Workflow ID is correct
  • Chat not loading? Check browser console (F12) for errors
  • Blank screen? Verify chatkit-server is running on port 3001

Stuck? ChatKit troubleshooting

Step 5: Enhance with Codex (10 minutes)

Goal: Use Codex to add features without writing code manually.

5.1 Install Codex IDE extension (2 min)

For VS Code:

  1. Open VS Code
  2. Go to Extensions (Cmd+Shift+X or Ctrl+Shift+X)
  3. Search "Codex"
  4. Install "Codex" by OpenAI
  5. Sign in with your ChatGPT account when prompted

Success: You see the Codex icon in your sidebar.

Other editors:

5.2 Add a feature with Codex (5 min)

  1. Open your project in VS Code
  2. Click the Codex icon in the sidebar
  3. Type this prompt:

Add a "Quick Tips" sidebar to index.html that shows helpful study tips.
The tips should rotate every 10 seconds. Include tips like:
- Take breaks every 25 minutes
- Explain concepts out loud to solidify understanding
- Practice problems are more effective than rereading notes
- Sleep is crucial for memory consolidation

Style it to match the purple theme.

  1. Press Enter and watch Codex work

Success: Codex modifies your HTML file and adds the sidebar with rotating tips.

5.3 Fix any bugs (3 min)

If something doesn't work, ask Codex:

The tips aren't rotating. Debug and fix the JavaScript.

Codex will:

  • Read your files
  • Identify the issue
  • Propose and apply a fix

Success: Tips rotate smoothly every 10 seconds.

Pro tip: Be specific! "Add error handling to the session endpoint" works better than "make it better."

Stuck? Codex prompting guide

Step 6: Deploy to Production (5 minutes)

Goal: Make your app accessible to anyone, not just localhost.

6.1 Choose a deployment platform (1 min)

Easiest: Railway (recommended for this tutorial)

bash

# Install Railway CLI
npm install -g railway

# Login
railway login

Alternative: Vercel

bash

npm install -g vercel
vercel login

6.2 Deploy (3 min)

Using Railway:

bash

# Initialize Railway project
railway init

# Add environment variable
railway variables set OPENAI_API_KEY=sk-your-key-here

# Deploy
railway up

Railway will give you a URL like https://study-buddy-production.railway.app

Using Vercel:

bash

# Set environment variable
vercel env add OPENAI_API_KEY

# Deploy
vercel --prod

Success: You get a public URL where your app is live.

6.3 Update your ChatGPT connector (1 min)

  1. Go to ChatGPT Settings → Connectors → Study Assistant → Edit
  2. Update Connector URL to your production URL + /mcp
  3. Click Save
  4. Click Refresh to reload the tools

Success: Your app works in ChatGPT with your production URL!

Troubleshooting:

  • Deployment fails? Check your package.json has a start script
  • 500 errors? Check environment variables are set correctly
  • Deployment guide

Step 7: Add Production Features (5 minutes)

Goal: Make your app reliable and observable.

7.1 Add basic logging (2 min)

Open src/server.ts and wrap your tool handler:

typescript

mcp.registerTool(
 "help_with_homework",
 
// ... existing config ...
 async ({ question, subject }) => {
   const startTime = Date.now();
   
   try {
     const answer = {
       
// ... existing logic ...
     };
     
     
// Log success
     console.log(JSON.stringify({
       timestamp: new Date().toISOString(),
       tool: "help_with_homework",
       subject,
       latency_ms: Date.now() - startTime,
       status: "success"
     }));
     
     return {
       structuredContent: answer,
       content: [{
         type: "text",
         text: `I've prepared a detailed explanation for your ${subject} question.`
       }]
     };
   } catch (error) {
     
// Log errors
     console.error(JSON.stringify({
       timestamp: new Date().toISOString(),
       tool: "help_with_homework",
       latency_ms: Date.now() - startTime,
       status: "error",
       error: error.message
     }));
     throw error;
   }
 }
);

7.2 Optimize your metadata (3 min)

Go to ChatGPT Settings → Connectors → Study Assistant → Edit

Update description to:

Use this tool when students need help with homework questions in math,
science, english, or history. Provides clear explanations with step-by-step
guidance.

Use when:
- Student asks "help me with..." followed by a subject
- Student poses a specific homework question
- Student needs concept explanation

Do not use for:
- General conversation
- Homework questions outside the four subjects
- Requests for complete essay writing

Add starter prompts:

  • "Help me understand the Pythagorean theorem"
  • "What causes photosynthesis?"
  • "Explain what a metaphor is"

Click Save and Refresh.

Success: Your app is more discoverable and ChatGPT routes to it more accurately.

🎉 Congratulations! You Built It All!

You now have a production-ready AI application using the entire DevDay 2025 stack:

Apps SDK - Custom app inside ChatGPT with beautiful UI
AgentKit - Multi-agent workflow with intelligent routing
ChatKit - Embedded chat interface on your own website
Codex - AI-powered feature development
Production ready - Deployed, logged, and optimized

What you can do now:

View your live app: Go to your production URL
Test in ChatGPT: Open ChatGPT, enable Study Assistant, ask homework questions
Check logs: Run railway logs or check your deployment platform
Add features: Use Codex to enhance without manual coding

Next Steps & Resources

Expand Your App

Add more subjects:

bash

codex
# Ask: "Add support for chemistry and physics with specialized agents"

Add authentication:

Add voice support:

bash

codex
# Ask: "Integrate gpt-realtime-mini for voice homework help"

Add memory:

Level Up with Advanced Features

Create custom widgets:

Add guardrails:

Set up evals:

Use Advanced Models

Add GPT-5 Pro for complex questions:

typescript

// In your agent builder, switch model to gpt-5-pro// Or update your MCP server to use GPT-5 Pro API

GPT-5 Pro docs

Add video generation with Sora 2:

bash

codex
# Ask: "Add a feature that generates visual explanations # of concepts using Sora 2 API"

Sora 2 API guide

Get Help

Documentation:

Troubleshooting:

Community:

Examples:

Common Issues & Quick Fixes

"Failed to create session"

  • Check your Workflow ID is correct in chatkit-server.ts
  • Verify your OpenAI API key has ChatGPT access
  • Make sure you published your workflow in Agent Builder

"No tools listed" in ChatGPT

  • Verify your MCP server is running
  • Check ngrok/production URL is correct with /mcp endpoint
  • Look at server logs for errors

"Agent not routing correctly"

  • Refine your classifier agent instructions
  • Add more examples to guide routing
  • Test with Preview in Agent Builder first

"Codex not understanding my request"

  • Be more specific: "Add X to Y file with Z styling"
  • Provide context: "Looking at index.html, add..."
  • Show examples: "Like this: [example code]"

"Deployment failed"

  • Check package.json has correct scripts
  • Verify environment variables are set
  • Check logs: railway logs or platform-specific command

What You Learned

You just built a complete AI application from scratch in 60 minutes using:

  1. Apps SDK - Created an MCP server that exposes tools and renders custom UI inside ChatGPT
  2. AgentKit - Built a multi-agent system with intelligent routing using Agent Builder
  3. ChatKit - Embedded a chat interface into a custom website
  4. Codex - Enhanced your app with AI-powered coding assistance
  5. Production deployment - Made it live and accessible to the world

This same pattern works for any AI application:

  • Customer support bots
  • Research assistants
  • Task automation
  • Content creation tools
  • Educational platforms

The only limit is your imagination.

Now go build something amazing! 🚀

cat carticature

See you cool cats on X!

Get your brand in front of 550,000+ professionals here
www.theneuron.ai/newsletter/

Get the latest AI

email graphics

right in

email inbox graphics

Your Inbox

Join 550,000+ professionals from top companies like Disney, Apple and Tesla. 100% Free.