Authentication¶
Republic supports both static provider keys and dynamic provider token resolution.
Static API Keys¶
Use api_key when your process already has the provider token.
from republic import LLM
llm = LLM(
model="openrouter:openrouter/free",
api_key="<OPENROUTER_KEY>",
)
For multi-provider fallback, pass a provider-to-token mapping.
from republic import LLM
llm = LLM(
model="openai:gpt-4o-mini",
fallback_models=["anthropic:claude-3-5-sonnet-latest"],
api_key={
"openai": "<OPENAI_KEY>",
"anthropic": "<ANTHROPIC_KEY>",
},
)
Dynamic Key Resolution¶
Use api_key_resolver when the token should be resolved lazily per provider.
from republic import LLM
def resolve_api_key(provider: str) -> str | None:
if provider == "openrouter":
return "<OPENROUTER_KEY>"
if provider == "openai":
return "<OPENAI_KEY>"
return None
llm = LLM(
model="openrouter:openrouter/free",
api_key_resolver=resolve_api_key,
)
This is the right hook when:
- Tokens come from a local credential store.
- Different providers use different auth flows.
- Tokens may expire and need refresh logic.
OpenAI Codex OAuth¶
Republic exposes a dedicated login flow and resolver for OpenAI Codex-style OAuth.
from republic import LLM, login_openai_codex_oauth, openai_codex_oauth_resolver
login_openai_codex_oauth(
prompt_for_redirect=lambda authorize_url: input(
f"Open this URL and paste callback URL:\n{authorize_url}\n> "
),
)
llm = LLM(
model="openai:gpt-5.3-codex",
api_key_resolver=openai_codex_oauth_resolver(),
)
print(llm.chat("Say hello in one sentence."))
openai_codex_oauth_resolver() reads ~/.codex/auth.json by default, or
$CODEX_HOME/auth.json when CODEX_HOME is set. The resolver returns the current
OpenAI access token for provider openai and refreshes it automatically when
expiry is near.
See examples/06_openai_codex_oauth.py for a runnable example.
GitHub Copilot OAuth¶
Republic also supports GitHub device-flow OAuth for the github-copilot provider.
from republic import LLM, github_copilot_oauth_resolver, login_github_copilot_oauth
login_github_copilot_oauth(
device_code_notifier=lambda verification_uri, user_code: print(
f"Open {verification_uri} and enter code: {user_code}"
),
)
llm = LLM(
model="github-copilot:gpt-4.1",
api_key_resolver=github_copilot_oauth_resolver(),
)
print(llm.chat("Say hello in one sentence."))
github_copilot_oauth_resolver() reads the saved GitHub OAuth token from
~/.config/republic/github_copilot_auth.json by default, or
$XDG_CONFIG_HOME/republic/github_copilot_auth.json when XDG_CONFIG_HOME is set.
If no Republic auth file exists, the resolver also tries:
COPILOT_GITHUB_TOKENGH_TOKENGITHUB_TOKEN~/.config/gh/hosts.ymlgh auth token
The github-copilot provider reuses the standard any-llm OpenAI-compatible
client and points it at GitHub Models. Republic only owns the GitHub OAuth
token resolution and provider-specific default headers.
See examples/07_github_copilot_oauth.py for a runnable smoke test.
Recommendation¶
Use this split by default:
- Simple scripts:
api_key="<TOKEN>" - Multi-provider apps:
api_key={...}orapi_key_resolver=... - Local CLI integrations with existing auth state: provider-specific OAuth resolvers