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:
- ChatGPT Plus/Pro/Team/Enterprise (required)
- OpenAI API key (required)
- Ngrok account (free, for local testing)
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)
- Go to ChatGPT Settings → Connectors
- Scroll to Advanced → Enable Developer mode
- 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)
- Start a new ChatGPT conversation
- Click the + button next to the message box
- Select Developer mode
- Toggle on Study Assistant
- 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)
- Go to Agent Builder
- Click Create new workflow
- Choose Start from scratch
✅ Success: You see a visual canvas with a Start node.
3.2 Add the classifier (3 min)
- Drag an Agent node from the left sidebar
- 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
- Connect Start → Question Router
✅ Success: You have a connected agent node.
3.3 Add routing logic (3 min)
- Drag an If/Else node onto the canvas
- Connect Question Router → If/Else
- Configure:
- If condition:
output.text contains "math"
- Leave Then/Else empty for now
- If condition:
✅ Success: Your workflow has routing logic ready.
3.4 Add specialized agents (6 min)
Create Math Helper:
- Drag a new Agent node
- Name: Math Helper
- 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.
- Model: gpt-5
- Connect If/Else Then → Math Helper
Create General Helper:
- Drag another Agent node
- Name: General Helper
- Instructions:
You are a friendly homework assistant for science, english, and history.
Give clear explanations with examples. Be encouraging and supportive.
- Model: gpt-5
- Connect If/Else Else → General Helper
Connect to End:
- 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)
- Click Preview in the top right
- Test: "What is the Pythagorean theorem?"
- Verify it routes to Math Helper
- Test: "What causes rain?"
- Verify it routes to General Helper
- 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)
- Open http://localhost:3001 in your browser
- Type: "Help me solve x² + 5x + 6 = 0"
- 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:
- Open VS Code
- Go to Extensions (Cmd+Shift+X or Ctrl+Shift+X)
- Search "Codex"
- Install "Codex" by OpenAI
- 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)
- Open your project in VS Code
- Click the Codex icon in the sidebar
- 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.
- 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)
- Go to ChatGPT Settings → Connectors → Study Assistant → Edit
- Update Connector URL to your production URL +
/mcp
- Click Save
- Click Refresh to reload the tools
✅ Success: Your app works in ChatGPT with your production URL!
Troubleshooting:
- Deployment fails? Check your
package.json
has astart
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:
- Persist state guide
- Store student progress, favorite subjects, learning style
Level Up with Advanced Features
Create custom widgets:
Add guardrails:
- Guardrails documentation
- Protect against inappropriate content
- Mask PII automatically
Set up evals:
- Evals platform guide
- Track accuracy over time
- A/B test different prompts
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
Add video generation with Sora 2:
bash
codex
# Ask: "Add a feature that generates visual explanations # of concepts using Sora 2 API"
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:
- Apps SDK - Created an MCP server that exposes tools and renders custom UI inside ChatGPT
- AgentKit - Built a multi-agent system with intelligent routing using Agent Builder
- ChatKit - Embedded a chat interface into a custom website
- Codex - Enhanced your app with AI-powered coding assistance
- 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! 🚀