Codex best practices for persistent secrets

I’m trying to understand the best pattern for developers to pass and persist secrets in Codex. In my case, I’m using the cloud Codex interface and am connected to my GitHub repo. When my (Python) code runs, it makes API calls to various LLMs, so Codex needs access to the API keys as long as the container is running. Since the API keys are secret, I can’t check them into GitHub, of course.

I would typically handle this by creating a local, non-version-controlled .env file containing the API keys and then programmatically importing that into my environment. Since Codex creates its own container, I need to do something else. If I edit the Codex environment, I see that I can add <key, value> pairs in both an “Environment variables” and “Secrets” category. I believe the “Secrets” pairs are only available during the initial “setup script” step.

I assumed that the setup script is only run once in the container (e.g., to pip install packages at launch). However, I need access to the API keys whenever my code might be running in the container, not just at startup.

I can imagine a number of ways I might proceed:

  1. I could stick the API keys in the “Environment variables” list for persistent access, but then what is the purpose of “Secrets”?
  2. I could restrict the API keys to “Secrets” but then write a setup script that imports them to the environment, but that sounds equivalent but harder than just adding them to the “Environment variables” list directly.
  3. I could restrict the API keys to “Secrets” and launch some other key-management system in the setup script, but I don’t really want to add that complexity.

My use case seems pretty standard. What’s the preferred method of handling this?

1 Like

I have an opinion, not to be confused with authoritative advice :laughing:

I draw the line at handing over any secrets to an LLM that end up in its context, which gives the model carte blanche freedom to do whatever it wants, theoretically. Any work I do locally with agents wraps access to authenticated APIs in tool calls where secrets can be accessed deterministically in code.

Codex is an agent we have no ability to give explicit tool calling to, operating in an environment where it has read access to everything. I can’t conceive of a way to allow the agent to run code fully integrated with authenticated API calls in this environment that doesn’t violate my line in the sand. The runtime needs read access to the key in the very environment the Codex agent has access to.

Perhaps there is some sophisticated scheme that restructures the typical API key access in code to allow it to be provided to the runtime but not the agent, but I’m not sure this is worth the effort, based on my reasoning below.

Personally I see the Codex agent’s job as primarily development, unit testing and linting. Unit tests are flagged and integration tests are omitted in the codex environment so they don’t frustrate the agent. I instruct the agent to create integration tests for any new functionality , and it generally writes great tests that I can run after the PR is generated. This has been working exceedingly well for me and has become more than just acceptable to me…it almost feels like the separation of testing responsibility between the cloud agent and my local IDE (which is more of a pair workflow between me and local agent) is a value-add and not a limitation. In fact my confidence in the Codex PRs has gotten so high that I merge them without initial review on a regular basis, start the next task running, then review the changes locally, run integration tests, end-to-end test, while the next Codex task is running.

With this workflow I can keep codex running tasks nearly continuously, while absorbing the changes (mentally and repo-wise) while it works, and my early gut reaction of “oh no my application can’t run fully in the codex cloud because of API secrets” has entirely dissipated.

Thanks, Knavillus, that seems like a very sane approach, and your suggested division of labor between Codex and the developer makes sense.

I am a little disappointed not to allow Codex to run the code its writing. I suppose I could generate some Codex-specific API keys so that I can discard them when I’m done. Hmmm…

1 Like