LlamaIndex
LlamaIndex reads OPENAI_API_KEY from the environment by default. For a custom
endpoint the parameter is api_base (not base_url), and the class is
OpenAILike.
Start here if seekrit is new: three
commands put the keys in
an environment, mint a token bound to it, and export SEEKRIT_TOKEN. A token
reads everything in its
environment, so
there is no per-key or per-framework setup to do before any of the below.
1. Wrap the process
seekrit run -- python query.py
seekrit run -- uvicorn app:app
from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
Settings.llm = OpenAI(model="gpt-5.6-terra")
A RAG app usually needs more than the model key — a vector store URL, a database
password, an embedding provider. One seekrit run covers all of them; they are
the same environment.
2. Resolve in code
import seekrit
from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
secrets = seekrit.Client().resolve()
Settings.llm = OpenAI(model="gpt-5.6-terra", api_key=secrets["OPENAI_API_KEY"])
In a notebook, use the one-call form instead — it takes the token from a password
prompt when there isn't one in the environment, so it never gets saved into the
.ipynb, and it returns names rather than values so a displayed cell writes a
summary and nothing more:
import seekrit
seekrit.load()
3. Never hold the key
from llama_index.llms.openai_like import OpenAILike
Settings.llm = OpenAILike(
model="gpt-5.6-terra",
api_base="http://127.0.0.1:8080/openai/v1",
api_key="{{seekrit:OPENAI_API_KEY}}",
is_chat_model=True,
)
# seekrit-proxy.toml
listen = "127.0.0.1:8080"
[[route]]
prefix = "/openai"
upstream = "https://api.openai.com"
allow = ["OPENAI_API_KEY"]
methods = ["POST"]
paths = ["/v1/chat/completions", "/v1/embeddings"]
OpenAILike exists because the first-party OpenAI class assumes OpenAI's own
capabilities; tell it is_chat_model=True and, if you use tool calling,
is_function_calling_model=True.
Without running the proxy
Both OpenAI and OpenAILike take an http_client:
import httpx
from llama_index.llms.openai import OpenAI
from seekrit.transport import SeekritTransport
Settings.llm = OpenAI(
model="gpt-5.6-terra",
api_key="{{seekrit:OPENAI_API_KEY}}",
http_client=httpx.Client(
transport=SeekritTransport(allow={"api.openai.com": ["OPENAI_API_KEY"]}),
),
)
Weaker than the proxy, since it runs in your process:
in-process injection sets out the
trade-off. Remember Settings.embed_model needs the same treatment.
Gotchas
- Embeddings are a second route.
Settings.embed_modelbuilds its own client, so pointing onlySettings.llmat the proxy leaves embedding calls going direct. Set both, and keep/v1/embeddingsin the route'spaths. - Indexes get built once and read forever. A vector store credential often outlives the process that used it. That is a rotation question, not an injection one — see secret rotation.
- A notebook is the easiest place to leak a value.
print(secrets)in a cell writes plaintext into a file people commit.seekrit.load()exists to make the safe thing the short thing.