Codex is the coding agent I use for local work. ChatGPT is a separate application in my browser. I wanted to give Codex a draft, ask for a second opinion from ChatGPT, and get the answer back without moving the text and files myself.

The first prototype did that through my signed-in Chrome session. It could send a question, attach a small PDF, and continue the same conversation. But each Codex task also had to work out the browser procedure. A successful demonstration was not yet a dependable tool.

The prototype’s path was short, but the responsibility in the middle was broad:

flowchart TD
    U["My question or PDF"] --> C["Codex decides the next action"]
    C <--> T["General browser-control tools"]
    T <--> B["My signed-in Chrome"]
    B <--> G["ChatGPT conversation"]

Figure 1. Codex chose both what to ask and how to operate the page. The browser-control tools carried out individual actions; they did not own a durable round-trip contract.

1. Why use my existing browser?

My normal Chrome profile was already signed in and contained the conversations I wanted to continue. The prototype used that session directly; it did not need to copy cookies or ask me to sign in to another profile.

The input was a question, an optional PDF, and an optional saved conversation URL. The output should be ChatGPT’s answer and a link that a later task could reuse. That made a document-review round trip a useful first experiment: success was easy to recognize, and continuity mattered.

This external Chrome route was separate from the desktop app’s built-in browser. The latter has its own profile and permissions; its documentation, checked September 3, 2026, also describes file-upload and sensitive-action limits. The two surfaces should not be treated as interchangeable. OpenAI Browser documentation.

2. One request in the prototype

Suppose I asked Codex to have ChatGPT read a one-page PDF containing a verification token.

Codex selected the intended Chrome tab, attached the file, entered the question, and attempted submission. It then inspected the page until it found the reply. Finally, it returned the token and the saved conversation URL:

https://chatgpt.com/c/<conversation-id>

For a follow-up, Codex reopened that URL and repeated the procedure. The URL supplied continuity; the open tab’s position or title did not.

This division was convenient for exploration. Codex could inspect an unfamiliar page and adjust its next action. But it also meant that every request carried the burden of deciding whether an upload was ready, which message was new, and whether the answer had finished.

3. What the demonstration proved

I observed three narrow paths complete in my signed-in session:

Case Observed result What it established
Text question The requested token came back Basic prompt-and-reply exchange
One-page PDF ChatGPT returned the token from the file Attachment delivery and a small reading task
Follow-up The returned conversation URL stayed the same Continuity across requests

These were feasibility checks. They did not establish reliable completion detection, duplicate prevention, or safe recovery after a timeout. A one-line token could pass while a long review still failed.

4. Why I moved the procedure into local code

The fixed steps were not getting more interesting: choose the right conversation, replace any old draft, attach the selected PDF, send once, wait, and read the new answer. Repeating those decisions inside each Codex task made page changes expensive to diagnose.

More importantly, a failed tool call did not explain whether another attempt was safe. If ChatGPT accepted a message but the caller missed the acknowledgement, sending again could create a duplicate. If only a reply prefix was visible to the automation, returning it could look like success while losing most of the answer.

Those are state-management problems. A better instruction to “wait carefully” would not provide a durable record of an attempted send or correlate an extracted answer with the original question.

The replacement therefore moves the fixed procedure into local code. Codex decides what to ask. A narrow bridge decides how to carry out that authorized request, records what happened, and returns either checked text or an explicit failure. Page-specific fixes then live in one implementation with regression tests.

5. The lesson

The prototype was worth building because it proved the round trip was possible. It was worth replacing because possibility was the wrong success criterion for everyday use.

The next version needed to answer three questions: Did this request reach the intended conversation? Does this reply belong to it? And, if something failed, can we recover without sending again?

Part 2 follows those questions into the implementation. Its design lessons explain why moving the procedure into code still left identity, lifetime and testing mistakes to fix. The debugging reference records the hidden-page stall, attachment and citation failures, execution errors, worker restarts and the tests needed to distinguish a fix from a lucky pass. The September 24 additions explain how one changed page exposed several incomplete assumptions, from the input control to identifying the final answer. They distinguish page compatibility from state-model mistakes and tests that omitted the failing conditions.