Skip to main content
The OpenAI Apps SDK is the proprietary runtime for ChatGPT Apps, announced in October 2025. It extends MCP with interactive UI widgets that render directly inside ChatGPT conversations.

Widget Rendering Flow

Here’s what happens when ChatGPT renders a widget:
  1. User asks ChatGPT to perform an action (e.g., “Show me flight options to Paris”)
  2. ChatGPT calls your MCP tool (e.g., search_flights)
  3. Your tool returns a result with data and a reference to a UI resource
  4. ChatGPT fetches the resource (your compiled React component) and renders it in an iframe
  5. The widget is hydrated with your tool’s structuredContent and _meta properties
ChatGPT Apps Rendering Flow

The window.openai API

Widgets run inside an iframe and have access to a special window.openai global that enables communication with the host:
APIDescription
toolInputArguments supplied when the tool was invoked
toolOutputYour structuredContent — initial data passed from your tool
toolResponseMetadataThe _meta payload; only the widget sees it, never the model
widgetState / setWidgetState()Persist UI state across interactions
callTool()Trigger additional tool calls from the UI
sendFollowUpMessage()Send messages back into the chat
requestDisplayMode()Request inline, PiP, or fullscreen display
requestModal()Open a modal window outside the iframe
uploadFile()Upload files to host-managed storage
getFileDownloadUrl()Get download URLs for uploaded files
openExternal()Open external URLs safely
setOpenInAppUrl()Set URL for the “Open in <App>” button in fullscreen mode
This API is powerful but low-level and imperative—which is where Skybridge comes in.

Skybridge Hook Mapping

Skybridge wraps the raw window.openai API with React hooks:
Raw APISkybridge HookPurpose
window.openai.toolInput, toolOutput, toolResponseMetadatauseToolInfo()Access tool input, output, and _meta
window.openai.widgetState and window.openai.setWidgetStateuseWidgetState()Persistent widget state
window.openai.callTool()useCallTool()Make additional tool calls
window.openai.sendFollowUpMessage()useSendFollowUpMessage()Send follow-up messages
window.openai.openExternal()useOpenExternal()Open external URLs
window.openai.view and window.openai.requestModal()useRequestModal()Request modal display
window.openai.theme, maxHeight, safeAreauseLayout()Theme, max height, safe area insets
window.openai.locale, userAgentuseUser()Locale and device/capabilities
window.openai.displayMode and window.openai.requestDisplayModeuseDisplayMode()Access/change display mode
window.openai.uploadFile(), getFileDownloadUrl()useFiles()Upload and download files
window.openai.setOpenInAppUrl()useSetOpenInAppUrl()”Open in App” button URL in fullscreen

Apps SDK APIs not yet supported in Skybridge

The following Apps SDK widget APIs are not yet wrapped by Skybridge hooks:
Raw APIPurpose
window.openai.notifyIntrinsicHeight(...)Report dynamic widget heights to the host to avoid scroll clipping
window.openai.requestClose()Close the widget from the UI (e.g. user dismisses)
window.openai.requestCheckout(...)Open ChatGPT Instant Checkout UI (monetization)
You can call these directly on window.openai when running in ChatGPT, if needed. Support may be added in a future release.

Skybridge Apps SDK Exclusive Features

These features are only available in ChatGPT and not supported in MCP Apps:

File Operations

Upload and download files with host-managed storage:
import { useFiles } from "skybridge/web";

function Widget() {
  const { upload, getDownloadUrl } = useFiles();

  const handleUpload = async (file: File) => {
    const { fileId } = await upload(file);
    const { downloadUrl } = await getDownloadUrl({ fileId });
    // Use downloadUrl...
  };

  return <input type="file" onChange={handleUpload} />;
}

Open in App URL

Set a URL for the “Open in App” button that appears in fullscreen mode:
import { useSetOpenInAppUrl } from "skybridge/web";

function Widget() {
  const { setOpenInAppUrl } = useSetOpenInAppUrl();

  useEffect(() => {
    setOpenInAppUrl("https://myapp.com/view/123");
  }, []);

  return <div>Widget content</div>;
}

Testing in ChatGPT

Please see the Test Your App guide for more information.
ChatGPT has aggressive caching. Use DevTools for fast iteration, then test in ChatGPT for final validation. See Fast Iteration.