angee.agents.runtimes
Agent runtimes — the programs an agent is rendered into (claude-code, opencode).
An :class:Agent selects one of these by runtime_class (an ImplClassField keyed against ANGEE_AGENT_RUNTIME_CLASSES). The runtime owns the facts that differ between agent programs and that the inference provider does not know:
- which operator service template renders it (
service_template_name), - how it consumes an inference credential as container env (:meth:
auth_env) — the same Anthropic OAuth token feedsclaude-code'sCLAUDE_CODE_OAUTH_TOKENbutopencodereads onlyANTHROPIC_API_KEY, so the env block is a(runtime × provider × credential-kind)fact, not a provider-only one, - which credential kinds it can actually use (:attr:
supported_credential_kinds), so the provision flow refuses an unworkable pairing up front instead of rendering a service that silently falls back, - the secret payload synced to the operator (:meth:
auth_secret_value) — most runtimes sync the raw token, but OpenCode's OAuth path syncs a base64auth.json, - the model handle in its own convention (:meth:
model_handle).
The inference backend stays the owner of vendor-native primitives (the credential value and the vendor SDK's own api_key_env); a runtime composes those.
operator_secret_ref
def operator_secret_ref(secret_name: str) -> strReturn the operator placeholder that resolves to a stored secret in the container.
The single home of the ${secret.<name>} operator-secret contract that both the inference auth env and the per-MCP-server bearer env reference; the operator substitutes the value at compose-render, so it never transits the browser.
AgentRuntime
class AgentRuntime(ImplBase)Base agent runtime: the generic, API-key-only program (e.g. opencode).
Reads the provider's own api_key_env and renders the catalogue model handle verbatim. Subclasses override for runtime-specific auth shapes (claude-code's OAuth env) or handle conventions.
renders_service
@property
def renders_service() -> boolWhether this runtime renders an operator service (vs workspace-only).
supports_credential
def supports_credential(credential: Any) -> boolWhether this runtime can authenticate inference with credential.
Takes the whole credential (not just its kind) so a runtime can refuse a credential whose shape it can't use — e.g. an OAuth token with no refresh token — up front, not only an unsupported kind.
model_handle
def model_handle(model: Any) -> strReturn the selected model handle in this runtime's convention.
The generic runtime renders the catalogue handle verbatim (e.g. opencode's anthropic/claude-… provider-qualified handle).
auth_env
def auth_env(*, backend: InferenceBackend, credential: Any,
secret_name: str) -> dict[str, str]Return the container env block this runtime uses to authenticate inference.
Secret-bearing vars carry the operator ${secret.<name>} placeholder; the value is synced server-side. An unsupported credential kind fails here, at the runtime owner, before a service is rendered.
auth_secret_value
def auth_secret_value(credential: Any) -> strReturn the secret payload synced to the operator store for credential.
The value stored under the agent's inference secret name and that :meth:auth_env's ${secret.<name>} placeholder resolves to in the container. The generic runtime syncs the raw credential secret (API key or bearer token); a runtime needing a richer shape (OpenCode's OAuth auth.json) overrides this.
NoRuntime
class NoRuntime(AgentRuntime)Null-object runtime for a workspace-only agent — renders no service.
OpenCodeRuntime
class OpenCodeRuntime(AgentRuntime)OpenCode (ACP over a WebSocket): an API key, or Anthropic Personal-Plans OAuth.
A static key renders the provider's own key env (ANTHROPIC_API_KEY etc.). OpenCode has no env path for an OAuth token — it reads OAuth only from its native auth.json store and needs a community Anthropic auth plugin (bundled in the opencode service image) to refresh and bear the token. We sync that store as a base64 blob in :attr:oauth_env; the image entrypoint decodes it into OPENCODE_AUTH_CONTENT. base64 keeps the JSON (quotes, braces) opaque to YAML and the operator's secret substitution. The model handle is the catalogue's provider-qualified id (e.g. anthropic/claude-opus-4-8).
WARNING: using a Claude Pro/Max (Personal Plans) OAuth token in OpenCode is against Anthropic's terms and risks account suspension — OpenCode removed built-in support in 1.3.0. Prefer a static API-key credential. OAuth stays disabled until the operator sets :attr:oauth_enabled_setting and builds the opencode image with the auth plugin (see OPENCODE_ANTHROPIC_AUTH_PLUGIN in the service Dockerfile); enabling it without the plugin would silently drop Anthropic from the model list.
supports_credential
def supports_credential(credential: Any) -> boolAllow OAuth only when opted in (plugin bundled) and the token can be refreshed.
OpenCode's plugin renews the access token from the stored refresh token, so an OAuth credential carrying no refresh token would authenticate only until the short-lived access token expires — refuse it up front rather than provision an agent that dies silently. Static keys defer to the base (which OpenCode always supports).
auth_env
def auth_env(*, backend: InferenceBackend, credential: Any,
secret_name: str) -> dict[str, str]Render the OAuth auth.json env (base64), or the provider's static key env.
auth_secret_value
def auth_secret_value(credential: Any) -> strSync OpenCode's base64 auth.json for OAuth, else the raw key (static).
ClaudeCodeRuntime
class ClaudeCodeRuntime(AgentRuntime)Claude Code: Anthropic-native, accepts both a static key and an OAuth token.
An OAuth credential renders Claude Code's token env plus the Anthropic beta header; a static key renders the vendor ANTHROPIC_API_KEY. The handle is the provider's native model name (Claude Code talks to Anthropic directly).
model_handle
def model_handle(model: Any) -> strReturn the provider's native model name, falling back to the catalogue handle.
auth_env
def auth_env(*, backend: InferenceBackend, credential: Any,
secret_name: str) -> dict[str, str]Render Claude Code's OAuth token env (plus beta header), or the static key env.