OpenAI Codex
- env var
- OPENAI_CODEX_ACCESS_TOKEN
- auth
- Existing Pi, OMP, Codex or OpenCode OAuth login
- operations
- search
- results
- 10, up to 100 sources locally
This is the search available through a Codex login, not the separately billed OpenAI API. The adapter calls the ChatGPT backend with the hosted web_search tool. A model answer without a completed search is an error, not a search result.
Credentials
Log in with Pi, OMP, Codex or OpenCode, then search. No manual token export:
web search "Node.js release notes" --provider openai-codex --json
Pi and OMP tools reuse the invoking host's auth storage, including its refresh and broker support. Those credentials are scoped to one operation, so concurrent hosts do not share accounts.
Outside a host, automatic discovery reads saved logins in this order:
| Client | Default store | Overrides |
|---|---|---|
| Codex | ~/.codex/auth.json | CODEX_HOME |
| Pi | ~/.pi/agent/auth.json | PI_CODING_AGENT_DIR |
| OMP | ~/.omp/agent/agent.db, then legacy auth.json | PI_CODING_AGENT_DIR, OMP_PROFILE or legacy PI_PROFILE |
| OpenCode | ~/.local/share/opencode/auth.json | XDG_DATA_HOME |
Only OAuth access tokens are used. API keys, disabled OMP accounts and expired tokens are skipped. Discovery never writes login files, creates a database or rotates saved refresh tokens. Standalone callers need a usable saved access token; if it expired, open the owning client and let it refresh. Codex logins held only in an OS keyring are not read. OMP SQLite requires Node's optional node:sqlite builtin; the native OMP host resolver does not.
Choose a store with codex.authSource or OPENAI_CODEX_AUTH_SOURCE: auto (default), codex, pi, omp, opencode, or none to disable local and host discovery. A named source bypasses other stores and the invoking host.
Explicit codex.credentials wins over environment overrides, which win over automatic discovery. OPENAI_CODEX_ACCESS_TOKEN can still supply a bearer; OPENAI_CODEX_ACCOUNT_ID is optional when its JWT contains chatgpt_account_id. A partial environment override does not silently switch to a different account. OPENAI_API_KEY does not configure this provider.
In application code, explicit credentials remain an optional override:
import { createSearchProvider } from "@agntn/web";
const search = createSearchProvider("openai-codex", {
codex: {
credentials: {
accessToken: "your-oauth-access-token",
accountId: "your-chatgpt-account-id",
},
model: "gpt-5.5",
},
});
const results = await search.search("Node.js release notes", { maxResults: 5 });
For refresh, pass a callback instead of the fixed pair. Your login service owns token storage and concurrent refresh coordination:
import { createSearchProvider, type CodexCredentialProvider } from "@agntn/web";
export function createCodexSearch(credentials: CodexCredentialProvider) {
return createSearchProvider("openai-codex", { codex: { credentials } });
}
The callback receives { refresh, signal } and returns { accessToken, accountId? }, directly or through a promise. The account ID is derived from the access token when omitted. It runs before each search with refresh: false. After an authentication rejection it runs once more with refresh: true, then the adapter retries once using the new pair. Check expiry even on the first call. The library never handles a refresh token itself.
Explicit credentials and model take precedence over the environment. Instance configuration is local to that instance, it does not enroll a callback in the global auto or all flows.
Endpoint and results
POST https://chatgpt.com/backend-api/codex/responses, with Bearer auth, chatgpt-account-id, store: false, streaming enabled and tool_choice: { type: "web_search" }.
Results come only from structured search sources and url_citation annotations. They have url, title and an empty snippet. Generated prose is not a page excerpt. URLs that appear only in prose never become results.
import { searchProviderDetailed } from "@agntn/web";
const response = await searchProviderDetailed("openai-codex", "Node.js release notes", {
maxResults: 5,
summary: true,
});
console.log(response.results);
console.log(response.metadata?.answer);
The detailed helper uses the same automatic login discovery and explicit environment overrides. summary: true includes the generated answer in metadata.answer; it stays absent otherwise. Metadata also carries the returned model, request ID and token usage when available.
Limits and traps
- This is an experimental adapter for the Codex backend, not a stable public search API. Model access and subscription limits still apply.
- The default model is
gpt-5.5. Override it withcodex.modelorOPENAI_CODEX_MODELif your account needs another model that supports hosted web search. There is no hidden model fallback. maxResultscaps collected sources locally, not upstream search work. Default 10, maximum 100. It does not promise that many sources.- No paging, domain/date/category filters, highlights, full page text, reverse image search or URL reading. Detailed helpers report ignored filters.
autotries Codex after the existing API providers, before custom providers and SearXNG.allincludes it when a usable saved login, a native host resolver or explicit environment credentials are available. Discovery does not check subscription status or refresh tokens.- A search has a 90-second ceiling, including credential resolution and its one possible refresh. Caller cancellation and earlier deadlines still win. The transport rejects streams above 8 MiB and events above 1 MiB.
- The adapter does not retry metered requests after HTTP 429 or server errors. Automatic search may move to another configured provider under the library's normal fallback rules.
- OAuth credentials can only go to the fixed ChatGPT endpoint. Custom
baseURLvalues and HTTP redirects are refused. Error messages omit upstream bodies and credential callback diagnostics. - Do not put personal subscription credentials on a public explorer worker. Local configuration is enough to use the library and its tools.
Implementation: src/providers/openai-codex.ts. Protocol reference: the Codex search adapter in oh-my-pi.