Sites hosting
Publish the exact validated source with the shortest safe sequence. Treat the Sites connector descriptions as the source of truth for arguments and archive requirements.
Communicate clearly
Assume the user is a nontechnical knowledge worker. Keep source control,
credentials, IDs, commits, branches, archives, versions, packaging, connector
calls, and deployment polling out of user-facing messages. Usually send one
update when publishing begins, then the final URL or a plain-language blocker.
For example: Your site is ready. I’m publishing it privately now.
Rules
- Publish after a successful build unless the user requested local-only work.
- Publishing does not require browser preview or visual QA. Use the preview from
sites-building; do more browser work only when the user asks. A failed browser handoff does not block publishing. - Treat
public/screenshot.jpegas an optional deployment thumbnail. Preserve an existing file. Create or refresh it only when the user explicitly requests a Sites deployment thumbnail; a generic screenshot request does not count. Missing or failed capture never blocks validation, version saving, or deployment. - Store only
project_idplus optional logicald1andr2bindings in.openai/hosting.json. Manage runtime values through Sites.
Fast publish sequence
- Reuse the successful build from
sites-buildingwhen the source has not changed. Rebuild only when needed. - Call
create_siteonce for a new site. Persist itsproject_idin.openai/hosting.jsonand reuse the source write credential returned by that call. Reuse these values instead of rediscovering them. Retry only when the error explicitly identifies a temporary failure or slug conflict. Treat quota, permission, and access errors as terminal; do not change the slug speculatively. - Commit the exact validated source. Push it with the returned credential as a
per-command HTTP authorization header. Keep the credential out of remote
URLs and Git configuration. Use the pushed branch-head SHA as
commit_sha. - Package with this plugin's root-level
scripts/package-site.shhelper, passing the project directory and archive path. It stagesdist/, hosting metadata, and migrations; validates required files; and creates the archive. - Save one version with the connector using that
commit_shaand archive. - Prefer private deployment. Use
deploy_private_site_versionwhen available. If only shared or public deployment is available, callrequest_user_inputwith an approval choice that names the resolved access level, such asPublish publiclyorPublish to existing shared access, plusNot now; wait for the response, and calldeploy_site_versiononly after approval. - Poll
get_deployment_statusdirectly until deployment succeeds or fails. Use discovery calls only when an error requires them.
Existing sites and advanced capabilities
- Reuse an existing
project_idand valid source credential when available. - If a credential is absent or expired, obtain one with
create_source_repository_write_credentialand reuse it until expiry. - If the D1 schema changed, ensure generated migrations are present before packaging.
- Require
dist/server/index.js, static assets when emitted,dist/.openai/hosting.json, anddist/.openai/drizzle/**when migrations exist. - For non-vinext projects, use the established Cloudflare Workers-compatible build output and adapt staging only as required by the connector contract.
Handoff
After get_deployment_status reports status: "succeeded", call
open_in_codex without threadId so it defaults to the calling thread. Use
the exact deployed URL returned in that response:
target: { type: "browser", url: deployedUrl }.
Then return the deployed Sites URL and a concise description of what the user
can do. If the deployment is unsuccessful, do not call open_in_codex or
mention that the deployed URL could not be opened in the in-app browser;
explain the user-visible reason and next step. Keep source credentials and
temporary archives private. Do not include file paths, commands, build details,
IDs, commits, or version information unless the user asks.


